### 准备
## 目标
了解 Spring 如何初始化 bean 实例
##测试代码
gordon.study.spring.ioc.IOC04_Initialization.java
public class IOC04_Initialization {
public static void main(String[] args) {
Resource resource = new ClassPathResource("ioc/ioc04.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
BeanDefinitionReader reader = new XmlBeanDefinitionReader((BeanDefinitionRegistry) factory);
reader.loadBeanDefinitions(resource);
factory.addBeanPostProcessor(new InnerBeanPostProcessor());
InnerClass inner = factory.getBean("inner", InnerClass.class);
System.out.println("level: " + inner.level);
factory.destroySingleton("inner");
}
static class InnerBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("in postProcessBeforeInitialization()...");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("in postProcessAfterInitialization()...");
if (bean instanceof InnerClass) {
((InnerClass) bean).level = 3;
}
return bean;
}
}
static class InnerClass implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
private int level;
public InnerClass() {
System.out.println("construct InnerClass...");
}
@Override
public void setBeanName(String name) {
System.out.println("in setBeanName()..." + name);
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("in setBeanClassLoader()..." + classLoader);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("in setBeanFactory()..." + beanFactory);
}
public void setLevel(int level) {
System.out.println("in setLevel()...");
this.level = level;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("in afterPropertiesSet()...");
level = 2;
}
@Override
public void destroy() throws Exception {
System.out.println("in destroy()...");
}
public void init() {
System.out.println("in init()...");
}
public void exit() {
System.out.println("in exit()...");
}
}
}
ioc04.xml
<beans ...>
<bean id="inner" class="gordon.study.spring.ioc.IOC04_Initialization$InnerClass" init-method="init" destroy-method="exit">
<property name="level" value="1" />
</bean>
</beans>
执行结果
construct InnerClass...
in setLevel()...
in setBeanName()...inner
in setBeanClassLoader()[email protected]
in setBeanFactory()...org.s[email protected]2d8f65a4: defining beans [inner]; root of factory hierarchy
in postProcessBeforeInitialization()...
in afterPropertiesSet()...
in init()...
in postProcessAfterInitialization()...
level: 3
in destroy()...
in exit()...
### 分析
## 文档描述
BeanFactory 类的文档描述了 bean 生命周期中对外提供的扩展点。
Bean factory implementations should support the standard bean lifecycle interfaces as far as possible. The full set of initialization methods and their standard order is:
- BeanNameAware‘s setBeanName
- BeanClassLoaderAware‘s setBeanClassLoader
- BeanFactoryAware‘s setBeanFactory
- EnvironmentAware‘s setEnvironment
- EmbeddedValueResolverAware‘s setEmbeddedValueResolver
- ResourceLoaderAware‘s setResourceLoader (only applicable when running in an application context)
- ApplicationEventPublisherAware‘s setApplicationEventPublisher (only applicable when running in an application context)
- MessageSourceAware‘s setMessageSource (only applicable when running in an application context)
- ApplicationContextAware‘s setApplicationContext (only applicable when running in an application context)
- ServletContextAware‘s setServletContext (only applicable when running in a web application context)
- postProcessBeforeInitialization methods of BeanPostProcessors
- InitializingBean‘s afterPropertiesSet
- a custom init-method definition
- postProcessAfterInitialization methods of BeanPostProcessors
On shutdown of a bean factory, the following lifecycle methods apply:
- postProcessBeforeDestruction methods of DestructionAwareBeanPostProcessors
- DisposableBean‘s destroy
- a custom destroy-method definition
## 示例代码分析
InnerClass 首先通过默认构造函数被实例化,输出 construct InnerClass...
接着装配属性,调用 setLevel 方法设置 level 属性,输出 in setLevel()...
然后就开始初始化 bean。通过 AbstractAutowireCapableBeanFactory 的 initializeBean 方法。
接着,第1620行代码处理 BeanPostProcessors 的 beforeInitialization 扩展点(11)。遍历 List<BeanPostProcessor> beanPostProcessors,调用每个 BeanPostProcessor 的 postProcessBeforeInitialization 方法。
然后,第1624行代码调用初始化方法:如果 bean 是 InitializingBean 实例,则调用 afterPropertiesSet 方法(12);如果 XML 文件中还定义了 init-method,则通过反射调用 init-method(13)。此外,Spring 框架尽力保证同一个初始化方法不会执行多次(可以尝试将 init-method 修改为 "afterPropertiesSet",看看执行结果)。
最后,第1633行代码处理BeanPostProcessors 的 afterInitialization 扩展点(14)。遍历 List<BeanPostProcessor> beanPostProcessors,调用每个 BeanPostProcessor的 postProcessAfterInitialization方法。