SpringIOC & Bean对象生命周期

Spring IOC容器

概念解读:IOC控制反转容器,本身指一种设计思想。在Spring中,将原本在程序中手动创建对象的控制权交给Spring框架来管理,通过创建IOC容器管理所有的Java Bean实例,然后根据需要完成对应的实例注入

IOC容器创建过程

​ 在Spring中,IOC容器的顶层接口时BeanFactory,定义了IOC容器的基本功能。其中继承扩展了该接口的有很多,我们常用的就是ApplicationContext,其中常用的实现了ApplicationContext接口的类,也就是IOC容器有ClassPathXmlApplicationContext,这是通过读取XML配置文件创建的IOC容器。还有AnnotationConfigApplicationContext通过分析注解创建的IOC容器。放一个IDEA的继承结构:

BeanFactory

  • ApplicationContext 继承了 ListableBeanFactory,这个 Listable 的意思就是,通过这个接口,我们可以获取多个 Bean,大家看源码会发现,最顶层 BeanFactory 接口的方法都是获取单个 Bean 的。

  • ApplicationContext 继承了 HierarchicalBeanFactory,Hierarchical 单词本身已经能说明问题了,也就是说我们可以在应用中起多个 BeanFactory,然后可以将各个 BeanFactory 设置为父子关系

  • AutowireCapableBeanFactory 这个名字中的 Autowire 大家都非常熟悉,它就是用来自动装配 Bean 用的,但是仔细看上图,ApplicationContext 并没有继承它,不过不用担心,不使用继承,不代表不可以使用组合,如果你看到 ApplicationContext 接口定义中的最后一个方法 getAutowireCapableBeanFactory() 就知道了。

  • ConfigurableListableBeanFactory 也是一个特殊的接口,看图,特殊之处在于它继承了第二层所有的三个接口,而 ApplicationContext没有。这点之后会用到。

源码解析我就不做分析了,太多而且太繁琐,这里推荐一篇文章给大家,配合自己阅读源码有很大帮助:javadoop_ioc

我大概总结一下(基于XML)IOC容器创建过程:

  • 当我们通过ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext(configLocation)创建容器时,通过该类的构造器会进入到创建IOC容器得核心方法**refresh()**这个方法有几个重要步骤,如下
// 1 准备刷新 
this.prepareRefresh();
// 2 获取DefaultListableBeanFactory,将XML的信息解析为beanDefinition
// 并通过beanName->beanDefinition保存在Map中 《重点》
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
// 3 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
this.prepareBeanFactory(beanFactory);
// 4 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
this.postProcessBeanFactory(beanFactory);
// ...
// 5 注册所有的BeanFactory后置处理器,并调用 《重点》
this.invokeBeanFactoryPostProcessors(beanFactory);
// 6 注册所有的Bean后置处理器 《重点》
this.registerBeanPostProcessors(beanFactory);
// ...
//.... 
// 7 完成剩下的所有单实例Bean的实例化 《重点》
this.finishBeanFactoryInitialization(beanFactory);
// ...
  • 2 获取DefaultListableBeanFactory,将XML的信息解析为beanDefinition,这个步骤是重点,总结一下:

    • 实例化一个DefaultListableBeanFactory,然后拿着这个BeanFactory去加载BeanDefinitions

    javadoop_ioc:ApplicationContext 继承自 BeanFactory,但是它不应该被理解为 BeanFactory 的实现类,而是说其内部持有一个实例化的 BeanFactory(DefaultListableBeanFactory)

    • 将路径信息转化为Resource,找到XML配置文件,将其转化为Document对象
    • 然后先解析默认的默认的命名空间,在解析自定义的命名空间

    parseDefaultElement(ele, delegate):<import /><alias /><bean /><beans />

    parseCustomElement(ele):其他标签比如<mvc /><task /><context /><aop />

    • 拿默认的命名空间bean标签为例,会将标签中的信息解析为beanDefinitionbeanNamealiasesArray,并将其设置到BeanDefinitionHolder对象当中

    beanDefinition:bean定义信息,即对象的设置的各种属性信息,翻看一下BeanDefinition接口源码即可

    beanName:即bean对象的名字,XML配置的id或者name,注意是全类名

    aliasesArray:bean对象的别名

    • 最后DefaultListableBeanFactory通过beanDefinition注册Bean,就是通过**beanDefinitionMap.put(beanName, beanDefinition)将信息保存在一个Map当中,同时会通过beanDefinitionNames.add(beanName)**将注册过的beanName保存在一个ArrayList当中
    • 最后就完成了初始化 Bean 容器,但未初始化Bean<bean /> 配置也相应的转换为了一个个 BeanDefinition,然后注册了各个 BeanDefinition 到注册中心,并且发送了注册事件。
  • 7 完成剩下的所有单实例Bean的实例化 《重点》,本篇讲解IOC容器,所有其他重点这里不总结了

    • 通过**getBean(beanName)**创建实例,如果已经创建了(通常是我们拿到容器,调用getBean时),直接返回即可
    • 先初始化所有depend-on的bean
    • 然后考虑通过**InstantiationAwareBeanPostProcessor **返回一个代理对象
    • 没有返回代理对象则创建一个普通实例Bean,然后设置属性值,初始化bean

    initializeBean(初始化bean):包括init-method 、 InitializingBean 、BeanPostProcessor 等

    • 最后返回实例bean即可

更多细节参见javadoop_ioc

Bean对象生命周期

​ 如下图:

Bean对象生命周期

我们可以通过打印日志的方式验证Bean对象的整个生命周期,基于XML的方式:

  • 首先需要写一个Bean对象MyBean,实现DisposableBean(用于对象销毁做某些操作);InitializingBean(用于属性注入后做某些初始化操作),;BeanFactoryAware和BeanNameAware(用于设置BeanFactory和BeanName)这四个接口:
public class MyBean implements DisposableBean, InitializingBean, BeanFactoryAware, BeanNameAware {
    private String name;

    public void test(){
        System.out.println("16 调用MyBean的方法...");
    }

    public MyBean() {
        System.out.println("6 实例化bean...");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("8 为Bean注入属性...");
        this.name = name;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("10 执行BeanFactoryAware的setBeanFactory方法...");
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("9 执行BeanNameAware的setBeanName方法...");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("17 执行DisposableBean的destroy方法...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("12 执行InitializingBean的afterPropertiesSet方法...");
    }

    public void initInXml(){
        System.out.println("13 执行<bean>定义的init-method方法...");
    }

    public void destroyInXml(){
        System.out.println("18 执行<bean>定义的destroy-method方法...");
    }
}
  • 然后我们写一个BeanPostProcessor接口的实现类MyBeanPostProcessor(用于Bean对象初始化前后做某些操作):
public class MyBeanPostProcessor implements BeanPostProcessor {

    public MyBeanPostProcessor() {
        super();
        System.out.println("3 实例化自定义的BeanPostProcessor实现类MyBeanPostProcessor...");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("11 调用MyBeanPostProcessor的postProcessBeforeInitialization方法...");
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("14 调用MyBeanPostProcessor的postProcessAfterInitialization方法...");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}
  • 然后我们写一个BeanFactoryPostProcessor接口的实现类MyBeanFactoryPostProcessor(用于对BeanFactory做某些操作):
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public MyBeanFactoryPostProcessor() {
        super();
        System.out.println("1 实例化BeanFactoryPostProcessor的实现类MyBeanFactoryPostProcessor...");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("2 调用MyBeanFactoryPostProcessor的postProcessBeanFactory方法...");
    }
}
  • 然后我们写一个InstantiationAwareBeanPostProcessorAdapter类的子类MyInstantiationAwareBeanPostProcessor(用于Bean对象实例化前和Bean对象初始化后做某些操作):
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
    public MyInstantiationAwareBeanPostProcessor() {
        super();
        System.out.println("4 实例化InstantiationAwareBeanPostProcessorAdapter的实现类MyInstantiationAwareBeanPostProcessor...");
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.println("5 调用MyInstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法...");
        return super.postProcessBeforeInstantiation(beanClass, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("15 调用MyInstantiationAwareBeanPostProcessor的postProcessAfterInitialization方法...");
        return super.postProcessAfterInitialization(bean, beanName);
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        System.out.println("7 调用MyInstantiationAwareBeanPostProcessor的postProcessPropertyValues方法...");
        return super.postProcessPropertyValues(pvs, pds, bean, beanName);
    }
}
  • 配置XML文件application.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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">
    <bean id="MyBean" class="com.springlearn.MyBean" init-method="initInXml" destroy-method="destroyInXml">
        <property name="name" value="lihua"/>
    </bean>

    <bean id="MyBeanFactoryPostProcessor" class="com.springlearn.MyBeanFactoryPostProcessor"/>

    <bean id="MyBeanPostProcessor" class="com.springlearn.MyBeanPostProcessor"/>

    <bean id="MyInstantiationAwareBeanPostProcessor" class="com.springlearn.MyInstantiationAwareBeanPostProcessor"/>
</beans>
  • 编写测试类springApplication:
public class springApplication {
    public static void main(String[] args) throws Exception {

        ClassPathXmlApplicationContext xmlIOC = new ClassPathXmlApplicationContext("application.xml");
        MyBean myBean = xmlIOC.getBean(MyBean.class);
        myBean.test();
        xmlIOC.registerShutdownHook();
    }
}
  • 最终运行效果:
1 实例化BeanFactoryPostProcessor的实现类MyBeanFactoryPostProcessor...
2 调用MyBeanFactoryPostProcessor的postProcessBeanFactory方法...
3 实例化自定义的BeanPostProcessor实现类MyBeanPostProcessor...
4 实例化InstantiationAwareBeanPostProcessorAdapter的实现类MyInstantiationAwareBeanPostProcessor...
5 调用MyInstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法...
6 实例化bean...
7 调用MyInstantiationAwareBeanPostProcessor的postProcessPropertyValues方法...
8Bean注入属性...
9 执行BeanNameAware的setBeanName方法...
10 执行BeanFactoryAware的setBeanFactory方法...
11 调用MyBeanPostProcessor的postProcessBeforeInitialization方法...
12 执行InitializingBean的afterPropertiesSet方法...
13 执行<bean>定义的init-method方法...
14 调用MyBeanPostProcessor的postProcessAfterInitialization方法...
15 调用MyInstantiationAwareBeanPostProcessor的postProcessAfterInitialization方法...
16 调用MyBean的方法...
17 执行DisposableBean的destroy方法...
18 执行<bean>定义的destroy-method方法...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值