bean的生命周期 BeanPostProcessor和InstantiationAwareBeanPostProcessor详解

由于前面有一篇文章解释了spring如何解决bean循环依赖的问题,里面涉及了SmartInstantiationAwareBeanPostProcessor的切面,这次干脆把BeanPostProcessor和InstantiationAwareBeanPostProcessor一起讲了,也好巩固下知识点

基础知识:
Bean创建过程中的“实例化”与“初始化”名词

1、实例化(Instantiation): 要生成对象, 对象还未生成.
2、初始化(Initialization): 对象已经生成.,赋值操作。
在这里插入图片描述

演示:

我们用一个简单的Spring Bean来演示一下Spring Bean的生命周期。

1、首先是一个简单的Spring Bean,调用Bean自身的方法和Bean级生命周期接口方法,为了方便演示,它实现了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这4个接口,同时有2个方法,对应配置文件中的init-method和destroy-method。如下:

package springBeanTest;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

/**
 * @author qsk
 */
public class Person implements BeanFactoryAware, BeanNameAware,
        InitializingBean, DisposableBean {
   

    private String name;
    private String address;
    private int phone;

    private BeanFactory beanFactory;
    private String beanName;

    public Person() {
   
        System.out.println("【构造器】调用Person的构造器实例化");
    }


    // 这是BeanFactoryAware接口方法
    @Override
    public void setBeanFactory(BeanFactory arg0) throws BeansException {
   
        System.out
                .println("【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()");
        this.beanFactory = arg0;
    }

    // 这是BeanNameAware接口方法
    @Override
    public void setBeanName(String arg0) {
   
        System.out.println("【BeanNameAware接口】调用BeanNameAware.setBeanName()");
        this.beanName = arg0;
    }

    // 这是InitializingBean接口方法
    @Override
    public void afterPropertiesSet() throws Exception {
   
        System.out
                .println("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()");
    }

    // 这是DiposibleBean接口方法
    @Override
    public void destroy() throws Exception {
   
        System.out.println("【DiposibleBean接口】调用DiposibleBean.destory()");
    }

    // 通过<bean>的init-method属性指定的初始化方法
    public void myInit() {
   
        System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");
    }

    // 通过<bean>的destroy-method属性指定的初始化方法
    public void myDestory() {
   
        System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的初始化方法");
    }
}

主要流程为:
实例化 -> 属性赋值 -> 初始化 -> 销毁

主要逻辑都在doCreate()方法中,逻辑很清晰,就是顺序调用以下三个方法,这三个方法与三个生命周期阶段一一对应,非常重要,在后续扩展接口分析中也会涉及。

createBeanInstance() -> 实例化
populateBean() -> 属性赋值
initializeBean() -> 初始化

而beanpostProcessor和InstantiationAwareBeanPostProcessor作用于实例化阶段的前后,BeanPostProcessor作用于初始化阶段的前后,如下
在这里插入图片描述

BeanPostProcessor

BeanPostProcessor是spring非常重要的拓展接口,例如aop通过拓展接口生产代理bean等。接口有两个方法:

public interface BeanPostProcessor {
   

    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
   
        return bean;
    }
	@Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
   
        return bean;
    }

ApplicationContext类型的容器会自动发现和注册该类型的bean,通过BeanPostProcessor可以对bean进行定制化,接口作用域是所有bean创建。
1、postProcessBeforeInitialization触发时机在bean实例化(Instantiation)之后,所有初始化(Initialization)动作(包括 InitializingBean#afterPrpertiesSet() 和 定制化init-method())以前。
2、postProcessAfterInitialization触发时机在bean实例化(Instantiation)之后,所有初始化(Initialization)动作(包括 InitializingBean#afterPrpertiesSet() 和 定制化init-method())以后。同时还会在InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 和 FactoryBean(bean工厂)获得bean时候调用

BeanPostProcessor 的Demo

由于ApplicationContext可以自动发现并注册BeanPostProcessor,如下使用ApplicationContext类型容器实现一个简单demo。

1 public class BeanPostProcessorTest {
   
 2 
 3     private ApplicationContext applicationContext ;
 4 
 5     @Before
 6     public void beforeApplicationContext(){
   
 7         /**
 8          * ApplicationContext 自动注册 BeanPostProcessor 
 9          *  不需要手动注册
10          * */
11         applicationContext = new ClassPathXmlApplicationContext("ioc-beanPostProcessor.xml") ;
12     }
13 
14     @Test
15     public void test(){
   
16         Bean bean = applicationContext.getBean("bean", Bean.class) ;
17         System.out.println(bean);
18     }
19 
20     @After
21     public void after(){
   
22         ((ClassPathXmlApplicationContext)applicationContext).close();
23     }
24 }

BeanPostProcessorTest.java
1 public class Bean {
   
 2 
 3     public Bean(){
   
 4 
 5     }
 6 
 7     public Bean(String name){
   
 8         System.out.println("构造函数被调用啦");
 9         this.name = name ;
10     }
11 
12     private String name ;
13 
14 
15     public String getName() {
   
16         return name;
17     }
18 
19     public void setName(String name) {
   
20         this.name = name;
21     }
22 
23     @Override
24     public String toString() {
   
25         return "Bean{" +
26                 "name='" + name + '\'' +
27                 '}';
28     }
29 }

Bean.java
1 public class LogicBeanPostProcessor implements BeanPostProcessor {
   
 2 
 3     @Nullable
 4     @Override
 5     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
   
 6         System.out.println("LogicBeanPostProcessor.postProcessAfterInitialization 执行啦 beanName = " + beanName);
 7         return bean;
 8     }
 9 
10     @Nullable
11     @Override
12     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
   
13         System.out.println("LogicBeanPostProcessor.postProcessBeforeInitialization 执行啦 beanName = " + beanName);
14         return bean;
15     }
16 }

LogicBeanPostProcessor.java

结果:

构造函数被调用啦
LogicBeanPostProcessor.postProcessBeforeInitialization 执行啦 beanName = bean
LogicBeanPostProcessor.postProcessAfterInitialization 执行啦 beanName = bean
Bean{name=‘zhouxiaoxing’}

BeanPostProcessor源码分析:注册时机和触发点

1、注册BeanPostProcessor

在AbstractApplicationContext容器启动的refresh()会注册BeanPostProcessor,源码如下:

@Override
    public void refresh() throws BeansException, IllegalStateException {
   
        synchronized (this.startupShutdownMonitor) {
   
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
   
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                // 注册BeanPostProcessor 在bean创建的时候进行拦截
               registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
   
                if (logger.isWarnEnabled()) {
   
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
   
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

        ......

    /**
     * Instantiate and invoke all registered BeanPostProcessor beans,
     * respecting explicit order if given.
     * <p>Must be called before any instantiation of application beans.
     */
    protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    }

跟进PostProcessorRegistrationDelegate.registerBeanPostProcessors

public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
   

        /**
         * 此时bean的定义加载已经完成,但是还没有实例化。 获得所有BeanPostProcessor bean对应的beanName
         */
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

        /**
         * 注册日志BeanPostProcessor, 检测注册的bean是否为spring基础服务类并打印日志
         */
        // Register BeanPostProcessorChecker that logs an info message when
        // a bean is created during BeanPostProcessor instantiation, i.e. when
        // a bean is not eligible for getting processed by all BeanPostProcessors.
        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
        beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

        /**
         * 当有注册多个BeanPostProcessor接口时会按顺序进行,即 实现PriorityOrdered->实现Ordered->普通类型接口->内部系统MergedBeanDefinitionPostProcessor
         */
        // Separate between BeanPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        List
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值