Spring IOC 源码简单分析 04 - bean的初始化

Posted 首夜盲毒预言家

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring IOC 源码简单分析 04 - bean的初始化相关的知识,希望对你有一定的参考价值。

 

### 准备

## 目标

了解 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()...sun.misc.Launcher$AppClassLoader@73d16e93
in setBeanFactory()...org.springframework.beans.factory.support.DefaultListableBeanFactory@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:
  1. BeanNameAware\'s setBeanName 
  2. BeanClassLoaderAware\'s setBeanClassLoader 
  3. BeanFactoryAware\'s setBeanFactory 
  4. EnvironmentAware\'s setEnvironment 
  5. EmbeddedValueResolverAware\'s setEmbeddedValueResolver 
  6. ResourceLoaderAware\'s setResourceLoader (only applicable when running in an application context) 
  7. ApplicationEventPublisherAware\'s setApplicationEventPublisher (only applicable when running in an application context) 
  8. MessageSourceAware\'s setMessageSource (only applicable when running in an application context) 
  9. ApplicationContextAware\'s setApplicationContext (only applicable when running in an application context) 
  10. ServletContextAware\'s setServletContext (only applicable when running in a web application context) 
  11. postProcessBeforeInitialization methods of BeanPostProcessors 
  12. InitializingBean\'s afterPropertiesSet 
  13. a custom init-method definition 
  14. postProcessAfterInitialization methods of BeanPostProcessors 
 
On shutdown of a bean factory, the following lifecycle methods apply:
  1. postProcessBeforeDestruction methods of DestructionAwareBeanPostProcessors 
  2. DisposableBean\'s destroy 
  3. a custom destroy-method definition 
 

## 示例代码分析

InnerClass 首先通过默认构造函数被实例化,输出 construct InnerClass...
 
接着装配属性,调用 setLevel 方法设置 level 属性,输出 in setLevel()...
 
然后就开始初始化 bean。通过 AbstractAutowireCapableBeanFactory initializeBean 方法。
 
 
按照文档描述,Spring 框架先按顺序处理 BeanNameAware(1), BeanClassLoaderAware(2) 和 BeanFactoryAware(3),对应代码第1615行。
 
接着,第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,调用每个 BeanPostProcessorpostProcessAfterInitialization方法。
 

以上是关于Spring IOC 源码简单分析 04 - bean的初始化的主要内容,如果未能解决你的问题,请参考以下文章

Spring IOC 源码简单分析 01 - BeanFactory

Spring IOC 源码解析

Spring IOC 容器源码分析 - 余下的初始化工作

Spring IOC容器核心流程源码分析

Spring源码分析专题——目录

Spring源码剖析-基于注解的IOC启动流程