Spring IOC容器
4.1 Spring IoC容器和bean的介绍
IoC也被称为是依赖注入(DI)。先构造对象,设置属性等,然后容器在bean的时候注入那些依赖,控制反转(IoC)。
Bean本身控制实例化或直接地使用类的构造来定位它的依赖,或者是如服务定位器模式的机制。
org.springframework.beans和org.springframework.context包是Spring Framework的IoC容器的基础。BeanFactory接口提供高级的配置机制,可以管理任意类型的对象。ApplicationContext是BeanFactory的子接口。它添加了和Spring的AOP特性很简便的整合;消息资源处理(用于国际化i18n),事件发布;应用层特定的上下文,比如用于Web应用程序的WebApplicationContext。
BeanFactory提供了配置框架和基本功能,而ApplicationContext添加了更多企业级开发特定的功能。ApplicationContext是BeanFactory完整的超集。
一个Bean就是一个实例化并组装的对象,由Spring的IoC容器来管理。否则,bean就是应用程序中众多对象之一。Bean和它们之间的依赖,反射出由容器使用的配置元数据。
4.2 容器概述
ApplicationContext接口代表了Spring的IoC容器,负责实例化,配置和装配上述的bean。
容器获得指示来实例化某对象,配置并装配,这都是通过读取配置元数据实现的。配置元数据在XML中,Java注解或Java代码中来表示。
在独立的应用程序中,通常是来创建ClassPathXmlApplicationContext或FileSystemXmlApplicationContext的实例。XML是定义配置元数据的传统格式,你可以指示容器使用Java的注解或是代码作为元数据的格式,提供少量的XML配置声明来开启对这些额外的元数据格式的支持。
在很多应用场景中,明确的用户代码不需要实例化一个或者多个Spring IoC容器的实例。在ApplicationContext被创建和实例化后,就得到了一个完全配置的可执行系统或程序。
4.2.1 配置元数据
4.2.2 实例化容器
4.2.3 使用容器
ApplicationContext的getBean()其实是调用的FactoryBean的getObject()
4.3 Bean概述
在容器本身,这些bean代表了BeanDefinition对象
4.3.1 命名bean
4.3.2 实例化bean
使用构造方法实例化
使用静态工厂方法来实例化
使用实例工厂方法来实例化
4.8 容器扩展点
4.8.1 使用BeanPostProcessor来自定义bean
BeanPostProcessor接口定义了你可以提供实现自己的(或覆盖容器默认的)实例逻辑,依赖解析逻辑等的回调方法。在Spring容器完成实例化,配置和初始化bean之后实现一些自定义逻辑。
如果有多个BeanPostProcessor实例,还可以通过设置order属性来控制这些BeanPostProcessor执行的顺序。但BeanPostProcessor必须实现了Ordered接口。
注意
- BeanPostProcessor操作bean(对象)实例;也就是说,Spring的IoC容器实例化bean的实例,之后BeanPostProcessor来做它们要做的事情。
- 如果你在一个容器中定义了BeanPostProcessor,那么它仅仅会在那个容器中后处理bean。换句话说,一个容器中定义的bean不会被另外一个容器中定义的BeanPostProcessor来进行后处理,即便是两个容器都是相同继承链上的一部分。
ApplicationContext会自动检测任意实现了BeanPostProcessor接口的bean定义的配置元数据。ApplicationContext注册这些bean作为后处理器,那么它们可以在bean创建之后被调用。Bean的后处理器可以在容器中部署,就像其它bean那样。
BeanPostProcessor和AOP自动代理
实现了BeanPostProcessor接口的类是特殊的,会被容器不同对待。所有它们参照的BeanPostProcessor和bean会在启动时被实例化,作为ApplicationContext启动阶段特殊的一部分。接下来,所有的BeanPostProcessor以排序的方式注册并应用于容器中的其它bean。因为AOP自动代理作为BeanPostProcessor本身的实现,它们为自动代理资格的直接引用的既不是BeanPostProcessor也不是bean,因此没有织入它们的方面。
对于这样的bean,你应该看到一个信息级的日志消息:“Bean foo没有由所有BeanPostProcessor接口处理的资格(比如:没有自动代理的资格)”。
4.8.2 使用BeanFactoryPostProcessor自定义配置元数据
BeanFactoryPostProcessor操作bean的配置元数据;也就是说Spring的IoC容器允许BeanFactoryPostProcessor来读取配置元数据并在容器实例BeanFactoryPostProcessor以外的任何bean之前可以修改它。
可以配置多个BeanFactoryPostProcessor,也可以通过order属性来控制这些BeanFactoryPostProcessor执行的顺序。仅当BeanFactoryPostProcessor实现Ordered接口时才能设置这个属性。
注意
- 如果你想改变真实的bean实例(也就是说,从配置元数据中创建的对象),那么你需要使用BeanPostProcessor(在上面4.8.1节,“使用BeanPostProcessor来自定义bean”中描述)来代替。在BeanFactoryPostProcessor(比如使用BeanFactory.getBean())中来使用这些bean的实例虽然在技术上是可行的,但这么来做会引起bean过早实例化,违反标准的容器生命周期。这也会引发一些副作用,比如绕过bean的后处理。
- 而且,BeanFactoryPostProcessor的范围也是对每一个容器来说的。如果你使用了容器的继承的话,这就是唯一相关的点了。如果你在一个容器中定义了BeanFactoryPostProcessor,那么它只会用于在那个容器中的bean。一个容器中Bean的定义不会被另外一个容器中的BeanFactoryPostProcessor后处理,即便两个容器都是相同继承关系的一部分。
当在ApplicationContext中声明时,bean工厂后处理器会自动被执行,这就可以对定义在容器中的配置元数据进行修改。
ApplicationContext会自动检测任意部署其中,且实现了BeanFactoryPostProcessor接口的bean。在适当的时间,它用这些bean作为bean工厂后处理器。你可以部署这些后处理器bean作为你想用的任意其它的bean。
注意
和BeanPostProcessor一样,通常你不会想配置BeanFactoryPostProcessor来进行延迟初始化。如果没有其它bean引用Bean(Factory)PostProcessor,那么后处理器就不会被初始化了。因此,标记它为延迟初始化就会被忽略,即便你在<beans/>元素声明中设置default-lazy-init属性为true,那么Bean(Factory)PostProcessor也会正常被初始化。