基础包和接口
- 两大基础包:org.springframework.beans 和 org.springframework.context.
- 两个基础接口:
- BeanFactory: The BeanFactory interface provides an advanced configuration mechanism capable of managing any type of object.
- ApplicationContext: is a subinterface of BeanFactory
- In short, the BeanFactory provides the configuration framework and basic functionality, and the ApplicationContext adds more enterprise-specific functionality.
总之,BeanFactory 提供了管理各种对象的配置框架和基础功能,而ApplicationContext则添加了一些企业应用特定的功能。
Container Overview
- Interface org.springframework.context.ApplicationContext: represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the aforementioned beans.代表IoC容器,负责beans的实例化、配置和组装。
- Configuration metadata: 记录beans信息的数据,IoC容器以此来实例化beans。
- ApplicationContext接口有很多实现类,以在不同的场景下使用。如ClassPathXmlApplicationContext orFileSystemXmlApplicationContext 用于独立应用程序。
- High-level view of how Spring works
Using Container
XML中
<beans>
中属性概述<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
beans —— xml文件的根节点。
xmlns ——是XML NameSpace的缩写,因为XML文件的标签名称都是自定义的,自己写的和其他人定义的标签很有可能会重复命名,而功能却不一样,所以需要加上一个namespace来区分这个xml文件和其他的xml文件,类似于java中的package。
xmlns:xsi ——是指xml文件遵守xml规范,xsi全名:xml schema instance,是指具体用到的schema资源文件里定义的元素所准守的规范。即/spring-beans-4.0.xsd这个文件里定义的元素遵守什么标准。
bean的初始化(容器初始化过程或调用容器getBean())和销毁(调用容器close())
- 默认下,
<bean>
的scope属性是singleton。这种bean在创建IoC容器完成时,就已经初始化,且在初始化和销毁bean,容器会调用相应的init-method和destroy-method。可以通过depends-on指定beans初始化和销毁顺序。 - 而对于prototype的bean,容器关闭时,不会调用bean的destroy-method。所以,depends-on也不能指定beans销毁的顺序。
- 默认下,
- By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process. 再一次强调singleton beans在容器初始化过程中被创建和配置(读取XML配置文件并加载上下文定义)。
Bean OverView
- Bean definition: IoC container读取XML配置文件(configuration metadata),并将
<bean>
封装成BeanDefinition。
- 容器ApplicationContext也可以利用getBeanFactory()得到DefaultListableBeanFactory,来注册已经存在的不在容器内的对象。
但通常是使用metadata bean definitions,即BeanDefinition。 - 注意,已存在的Singleton Bean和metadata可以被覆写,但注意会造成并发访问异常和不一状态的可能。
Dependencies
- By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process.
- A lazy-initialized bean tells the IoC container to create a bean instance when it is first requested, rather than at startup.
Lazy-initialized 告诉容器当被请求时才create实例,而不是在startup的时候。 - Method injection
- Lookup method injection
- Arbitrary method replacement
Bean scopes
- The singleton scope
This single instance is stored in a cache of such singleton beans, and all subsequent requests and references for that named bean return the cached object.
- The prototype scope
- As a rule, use the prototype scope for all stateful beans and the singleton scope for stateless beans.
- In contrast to the other scopes, Spring does not manage the complete lifecycle of a prototype bean: the container instantiates, configures, and otherwise assembles a prototype object, and hands it to the client, with no further record of that prototype instance.Prototype bean 实例化、配置、装配完成后,将对象交给客户端,并没有进一步记录该对象,所以Spring没有管理其完整的生命周期。
- Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called.Spring能管理任何Bean的初始化生命周期(通过回调方法),但不能管理prototype bean的释放。
- To get the Spring container to release resources held by prototype-scoped beans, try using a custom bean post-processor, which holds a reference to beans that need to be cleaned up.通过使用自定义的bean post-processor可以解决prototype-scoped beans的释放。
Singleton beans with prototype-bean dependencies
当一个singleton bean A 在每次方法调用的时候都需要一个non-singleton bean B,此时就会产生这样一个问题,因为A为singleton,所以容器只会创建一次A,那么也只有一次机会来创建A的属性,无论你是通过setter还是constructor方式注入Bean B,Bean B也只能被初始化一次,而实际需求是我们调用每个方法的时候都需要一个新的Bean B实例。
可以使用Method injection解决这个问题。- Method injection
牺牲了一些控制反转的特性。
如: Suppose singleton bean A needs to use non-singleton (prototype) bean B, perhaps on each method invocation on A.
You can make bean A aware of the container by implementing the ApplicationContextAware interface, and by making a getBean(“B”) call to the container ask for (a typically new) bean B instance every time bean A needs it.
Lookup Method injection
Lookup方法注入就是动态的替换掉Spring bean容器内原有的bean,生成一个新的且兼容的bean(和被替换掉的bean完全兼容,是其子类)返回给应用程序。
Spring配置文件修改如下:
<bean id="command" scope="prototype"/> <bean id="commandManager"> <lookup-method name="createCommand" bean="command"/> </bean>
Spring 会通过CGLIB动态生成一个子类,继承CommandManager ,并重写原有的createCommand()方法,再根据配置信息createCommand()方法会自动返回一个command bean。
CommandManager cm = (CommandManager) appContext.getBean("commandManager"); System.out.println(cm.createCommand().equals(cm.createCommand())); // false
CGLIB
Arbitrary method replacement
- Method injection