Bean创建全过程(附Bean生命周期、AOP对象创建过程)

一、Bean

Bean创建过程

Spring bean到底是如何创建的?(上) (qq.com)

1. BeanDefinition读取注册

Spring容器启动时,先按照声明bean的方式(注解、xml等)去读取所有bean的配置信息(类名,是否单例,初始化方法名称等),然后将这些BD存放一个在map中。在DefaultListableBeanFactory类中。

通过注解扫描出来的Bean的BeanDefinition用ScannedGenericBeanDefinition来表示。
配置类的BeanDefinition用AnnotatedGenericBeanDefinition来表示。
用@Bean声明的Bean的BeanDefinition用ConfigurationClassBeanDefinition来表示。


2. 获取Bean&三级缓存防止循环依赖

Spring 循环依赖,三级缓存注入代理对象_spring三级缓存代理对象-优快云博客

三级缓存其实是三个Map

假设A、B存在循环依赖:

@Component
public class A {
    @Resource
    private B b;
}

@Component
public class B {
    @Resource
    private A a;
}
  1. 首先对a这个bean调用AbstractBeanFactory#doGetBean(),会先尝试从三级缓存中获取。

  2. 获取失败,调用 getSingleton()方法。然后调用createBean() --> doCreateBean对该Bean进行实例化、属性注入、初始化等。

    1. 实例化:通过反射创建一个A对象,放入第三级缓存中(singletonFactories)。
    2. 属性注入:对这个对象进行属性依赖的注入,发现需要名为b的Bean,再次调用doGetBean() --> getSingleton()发现三级缓存中均不存在b,于是开始创建b。
    3. b的创建过程和a一样,只不过在属性注入的时候发现a存在第三级缓存中,成功注入了a,并且将a放到第二级缓存,b成功创建。
    4. a进行初始化
  3. ab均创建完成。

3. doCreateBean过程

在这里插入图片描述

AbstractAutowireCapableBeanFactory类中,使用了doCreateBean() 方法创建Bean。

主要干三件事情:

  1. 反射实例化 bean 对象: createBeanInstance()
  2. 属性注入: populateBean()
  3. 初始化 bean 对象: initializeBean()



Bean的生命周期

Bean的生命周期也就是从doCreateBean()开始

五步骤版本

五步骤版本:
1. 实例化
2. 依赖注入
3. 初始化
4. 使用Bean
5. 销毁Bean
  • 实例化:调用构造方法,或者是使用工厂模式构造bean
    <!--第一种方式-->
    <bean id="bean1" class="demo3.Bean1"></bean>
    <!--第二种方式:静态工厂,调用工厂中静态方法-->
    <bean id="bean2" class="demo3.Bean2Factory" factory-method="getBean2"></bean>
    <!--第三种方式:动态工厂,调用内部方法-->
    <bean id="bean3Factory" class="demo3.Bean3Factory"></bean>
    <bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean>
</beans>

  • 依赖注入:对Setter或者@Resource标注的属性进行赋值。spring.xml中对setter赋值。

  • 初始化:自定义了初始化方法并且在 init-method中指定,可实现如数据库初始连接等操作。

    <bean id="dog" class="com.example.springbeanlife.bean.Dog" init-method="myInit" destroy-method="myDestroy">
        <property name="name" value="小狗"/>
    </bean>
  • 销毁:调用了容器.close()或关闭程序后,会调用在destroy-method中指定的销毁方法。

七步骤版本

增加一个BeanPostProcessor

BeanPostProcessor

七步骤版本:
1. 实例化
2. 依赖注入
    3. 初始化前 BeanPostProcessor before方法
4. 初始化
    5. 初始化后 BeanPostProcessor after方法
6. 使用Bean
7. 销毁Bean

实现BeanPostProcessor接口

public class MyProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
       if ("dog".equals(beanName)){
           System.out.println("3. 初始化前 BeanPostProcessor before方法");
       }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("dog".equals(beanName)){
            System.out.println("5. 初始化后 BeanPostProcessor after方法");
        }
        return bean;
    }
}

注册BeanPostProcessor为Bean。BeanPostProcessor的执行顺序与注册到Spring的顺序有关。

<!--先执行processor再执行processor2-->
<bean id="processor" class="com.example.springbeanlife.bean.MyProcessor"/>
<bean id="processor2" class="com.example.springbeanlife.bean.MyProcessor2"/>

十步骤版本

增加三个接口

十步骤版本:
----实例化----
    1. 实例化
----依赖注入---
    2. 依赖注入
----初始化----
  ※3. BeanNameAware BeanFactoryAware 方法
    4. 初始化前 BeanPostProcessor before方法
  ※5. InitializingBean接口方法
    6. 初始化
    7. 初始化后 BeanPostProcessor after方法
----使用----
    8. 使用Bean
----销毁----
  ※9. DisposableBean接口方法执行
    10. 销毁Bean
  • XXXAware:通常Aware有这样一个规则:Aware接口的名称,表示依赖对象的类名称。
    例如,一个bean需要使用ApplicationContext,实现ApplicationContextAware接口即可。

  • InitializingBean:实现一个afterPropertiesSet()初始化方法

  • DisposableBean:实现销毁方法。bean初始化后,会被放入disposableBeans的Map集合中,spring关闭时会发布事件,调用lifecycleProcessor.onClose(),循环遍历这个Map,逐个执行销毁方法,可用于释放资源等。

二、BeanPostProcessor

可看看上个标题Bean的生命周期中有提到,BeanPostProcessor是在Bean初始化前后增加方法的。

如何触发before和after方法的呢?

Spring会在某个Bean初始化过程之前&之后(环绕初始化方法)会针对该对象分别调用所有BeanPostProcessor对象的方法。

BeanPostProcessor接口实现如下(AOP就是将原本Bean对象包装成代理类然后return)

public class MyProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
       if ("dog".equals(beanName)){
           System.out.println("3. 初始化前 BeanPostProcessor before方法");
       }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("dog".equals(beanName)){
            System.out.println("5. 初始化后 BeanPostProcessor after方法");
        }
        return bean;
    }
}


对两个方法打断点查看调用栈后进入了initializeBean(),如图:

  • Aware:invokeAwareMethods()方法调用该Bean实现的所有Aware接口

  • Before:applyBeanPostProcessorsBeforeInitialization即是调用所有BeanPostProcessorpostProcessBeforeInitialization方法。(接下来进入这个方法源码中)

  • 初始化:invokeInitMethods调用该Bean的所有初始化方法,包括注册的 init-method或者实现InitializingBean接口的方法。

  • After:applyBeanPostProcessorsAfterInitialization即是调用所有BeanPostProcessorpostProcessAfterInitialization方法


在这里插入图片描述

如图,getBeanPostProcessors()获取当前所有的BeanPostProcessors对象,并且对当前Bean循环调用它们的Before方法。

在这里插入图片描述


BeanPostProcessors的执行顺序与其注册到Spring的顺序有关。

  <bean id="processor2" class="com.example.springbeanlife.bean.MyProcessor2"/>
  <bean id="processor" class="com.example.springbeanlife.bean.MyProcessor"/>

在这里插入图片描述



三、 AOP代理对象是怎么创建的?

BeanPostProcessor —— 连接Spring IOC和AOP的桥梁 - 知乎 (zhihu.com)

​ 利用BPP,在before或after方法中对对象进行判断,查看该对象是否需要切面操作,如果需要的话就会生成该对象的代理对象并返回装配到bean中

​ 具体代码是在AbstractAutoProxyCreator类中实现的postProcessAfterInitialization

引用

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值