一 目录
二 官网介绍
2.1
模块化的思想是 Spring 中非常重要的思想。
Spring 框架是一个分层架构,每个模块既可以单独使用,又可与其他模块联合使用。
每个「绿框」,对应一个模块,总共8个模块;「黑色包」,表示要实现这个模块的 jar 包。
Core Container,我们刚才已经在文档里看到过了,就是 IoC 容器,是核心,可以看到它依赖于这4个 jar 包:
Beans
Core
Context
SpEL, spring express language
那这里我们就知道了,如果想要用 IoC 这个功能,需要把这 4个 jar 包导进去。其中,Core 模块是 Spring 的核心,Spring 的所有功能都依赖于这个 jar 包,Core 主要是实现 IoC 功能,那么说白了 Spring 的所有功能都是借助于 IoC 实现的。
2.1 官网 文档
learn—>reference doc
第一章 Overview,讲述它的历史、设计原理等等;
第二章 Core,包含了 IoC 容器,AOP 等等,那自然是讲 Spring 的核心了,要点进去好好看
总的来说:IOC控制反转最重要的就是容器和DI(依赖注入
)
三 容器概述
该org.springframework.context.ApplicationContext接口代表Spring IoC容器,并负责实例化,配置和组装Bean。容器通过读取配置元数据来获取有关要实例化,配置和组装哪些对象的指令。配置元数据以XML,Java批注或Java代码表示。它使您能够表达组成应用程序的对象以及这些对象之间的丰富相互依赖关系。
ApplicationContextSpring提供了该接口的几种实现。在独立应用程序中,通常创建ClassPathXmlApplicationContext 或的实例 FileSystemXmlApplicationContext。尽管XML是定义配置元数据的传统格式,但是您可以通过提供少量XML配置来声明性地启用对这些其他元数据格式的支持,从而指示容器将Java注释或代码用作元数据格式。
3.2实例化容器
使用 ApplicationContext,它是 BeanFactory 的子类,更好的补充并实现了 BeanFactory 的。
BeanFactory 简单粗暴,可以理解为 HashMap:
Key - bean name
Value - bean object
但它一般只有 get, put 两个功能,所以称之为“低级容器”。
而 ApplicationContext 多了很多功能,因为它继承了多个接口,可称之为“高级容器”。在下文的搭建项目中,我们会使用它。
提供给ApplicationContext构造函数的位置路ApplicationContext 的里面有两个具体的实现子类,用来读取配置配件的:
ClassPathXmlApplicationContext - 从 class path 中加载配置文件,更常用一些;
FileSystemXmlApplicationContext - 从本地文件中加载配置文件,不是很常用,如果再到 Linux 环境中,还要改路径,不是很方便。
当我们点开 ClassPathXmlApplicationContext 时,发现它并不是直接继承 ApplicationContext 的,它有很多层的依赖关系,每层的子类都是对父类的补充实现。
而再往上找,发现最上层的 class 回到了 BeanFactory,所以它非常重要。
要注意,Spring 中还有个 FactoryBean,两者并没有特别的关系,只是名字比较接近,所以不要弄混了顺序。
为了好理解 IoC,我们先来回顾一下不用 IoC 时写代码的过程。径是资源字符串,这些资源字符串使容器可以从各种外部资源(例如本地文件系统,Java等)加载配置元数据CLASSPATH。
ApplicationContext context = new ClassPathXmlApplicationContext(“services.xml”, “daos.xml”);
**bean 标签:告诉 Spring 要创建的对象 id: 对象的唯一标识,就像每个人的身份证一样,不可重复 class: bean 的完全限定名,即从 package name 到 class name property:给属性赋值,name 的名称取决于 set() 方法后面的参数** 四 为什么要用IOC这种思想 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200420174349493.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200420174359225.png) 如上图所示,本来 ABCD 是互相关联在一起的,**当加入第三方容器的管理之后,每个对象都和第三方法的 IoC 容器关联,彼此之间不再直接联系在一起了,没有了耦合关系,全部对象都交由容器来控制,降低了这些对象的亲密度,就叫“解藕”。 ****Spring 也是用的 set() 方法,它只不过提供了一套更加完善的实现机制而已。** 五 DI注入 1.4.1. Dependency Injection Dependency injection (DI) is a process whereby objects define their dependencies (that is, the other objects with which they work) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies on its own by using direct construction of classes or the Service Locator pattern.
Code is cleaner with the DI principle, and decoupling is more effective when objects are provided with their dependencies. The object does not look up its dependencies and does not know the location or class of the dependencies. As a result, your classes become easier to test, particularly when the dependencies are on interfaces or abstract base classes, which allow for stub or mock implementations to be used in unit tests.
DI exists in two major variants: Constructor-based dependency injection and Setter-based dependency injection.
Constructor-based Dependency Injection
DI存在两个主要变体:基于构造函数的依赖注入和基于Setter的依赖注入。
基于构造函数的依赖注入
基于构造函数的DI是通过容器调用具有多个参数(每个参数代表一个依赖项)的构造函数来完成的。调用static带有特定参数的工厂方法来构造Bean几乎是等效的,并且本次讨论将构造函数和static工厂方法的参数视为类似。以下示例显示了只能通过构造函数注入进行依赖项注入的类:
public class SimpleMovieLister {
// the SimpleMovieLister has a dependency on a MovieFinder
private MovieFinder movieFinder;
// a constructor so that the Spring container can inject a MovieFinder
public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// business logic that actually uses the injected MovieFinder is omitted...
}
构造函数参数解析匹配通过使用参数的类型进行。如果Bean定义的构造函数参数中不存在潜在的歧义,则在实例化Bean时,在Bean定义中定义构造函数参数的顺序就是将这些参数提供给适当的构造函数的顺序。考虑以下类别
基于Setter的依赖注入
基于设置器的DI是通过在调用无参数构造函数或无参数static工厂方法以实例化您的bean 之后,在您的bean上调用setter方法来完成的。
下面的示例显示只能通过使用纯setter注入来依赖注入的类。此类是常规的Java。它是一个POJO,不依赖于容器特定的接口,基类或注释。
基于构造函数或基于setter的DI?
由于可以混合使用基于构造函数的DI和基于setter的DI,因此,将构造函数用于强制性依赖项,将setter方法或配置方法用于可选性依赖项是一个很好的经验法则。请注意,可以 在setter方法上使用@Required批注,以使该属性成为必需的依赖项。但是,最好使用带有参数的程序验证的构造函数注入。
Spring团队通常提倡构造函数注入,因为它使您可以将应用程序组件实现为不可变对象,并确保不存在必需的依赖项null。此外,构造函数注入的组件始终以完全初始化的状态返回到客户端(调用)代码。附带说明一下,大量的构造函数自变量是一种不好的代码味道,这意味着该类可能承担了太多的职责,应该对其进行重构以更好地解决关注点分离问题。
Setter注入主要应仅用于可以在类中分配合理的默认值的可选依赖项。否则,必须在代码使用依赖项的任何地方执行非空检查。setter注入的一个好处是,setter方法可使该类的对象在以后重新配置或重新注入。因此,通过JMX MBean进行管理是用于setter注入的引人注目的用例。
使用最适合特定班级的DI风格。有时,在处理您没有源代码的第三方类时,将为您做出选择。例如,如果第三方类未公开任何setter方法,则构造函数注入可能是DI的唯一可用形式。