Spring 框架Bean的初始化和銷燬---方式:BeanPostProcessor後置處理器

BeanPostProcessor後置處理器概述

首先,我們來看下BeanPostProcessor的源碼,看下它到底是個什麼鬼,如下所示。

package org.springframework.beans.factory.config;
import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;
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;
    }
​
}

 

從源碼可以看出:BeanPostProcessor是一個接口,其中有兩個方法,postProcessBeforeInitialization和postProcessAfterInitialization兩個方法,這兩個方法分別是在spring容器中的bean初始化前後執行,所以spring容器中的每一個bean對象初始化前後,都會執行BeanPostProcessor接口的實現類的這兩個方法。

也就是說,postProcessBeforeInitialization方法會在bean實例化和屬性設置之後,自定義初始化方法之前被調用,而postProcessAfterInitialization方法會在自定義初始化方法之後被調用。當容器中存在多個BeanPostProcessor的實現類時,會按照它們在容器中註冊的順序執行。對於自定義BeanPostProcessor實現類,還可以讓其實現Ordered接口自定義排序。

因此我們可以在每個bean對象初始化前後,加上自己的邏輯。實現方式:自定義一個BeanPostProcessor接口的實現類MyBeanPostProcessor,然後在類MyBeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法裏面寫上自己的邏輯。

BeanPostProcessor後置處理器實例

我們創建一個MyBeanPostProcessor類,實現BeanPostProcessor接口,如下所示。

package io.mykit.spring.plugins.register.bean;
​
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
​
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
​
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("調用了postProcessBeforeInitialization方法,beanName = " + beanName + ", bean = " + bean);
        return bean;
    }
​
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("調用了postProcessAfterInitialization,beanName = " + beanName + ", bean = " + bean);
        return bean;
    }
}

 

接下來,我們運行BeanLifeCircleTest類的testBeanLifeCircle04()方法,輸出的結果信息如下所示。

調用了postProcessBeforeInitialization方法,beanName = animalConfig, bean = io.mykit.spring.plugins.register.config.AnimalConfig$$EnhancerBySpringCGLIB$$e8ab4f2e@56528192
調用了postProcessAfterInitialization,beanName = animalConfig, bean = io.mykit.spring.plugins.register.config.AnimalConfig$$EnhancerBySpringCGLIB$$e8ab4f2e@56528192
Cat類的構造方法...
調用了postProcessBeforeInitialization方法,beanName = cat, bean = io.mykit.spring.plugins.register.bean.Cat@1b1473ab
Cat的postConstruct()方法...
Cat的init()方法...
調用了postProcessAfterInitialization,beanName = cat, bean = io.mykit.spring.plugins.register.bean.Cat@1b1473ab
Cat的preDestroy()方法...
Cat的destroy()方法...

 

可以看到,postProcessBeforeInitialization方法會在bean實例化和屬性設置之後,自定義初始化方法之前被調用,而postProcessAfterInitialization方法會在自定義初始化方法之後被調用。

也可以讓實現Ordered接口自定義排序,如下所示。

package io.mykit.spring.plugins.register.bean;
​
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
​
/**
 * @author binghe
 * @version 1.0.0
 * @description 測試BeanPostProcessor
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor, Ordered {
​
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("調用了postProcessBeforeInitialization方法,beanName = " + beanName + ", bean = " + bean);
        return bean;
    }
​
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("調用了postProcessAfterInitialization,beanName = " + beanName + ", bean = " + bean);
        return bean;
    }
​
    @Override
    public int getOrder() {
        return 3;
    }
}

 

再次運行BeanLifeCircleTest類的testBeanLifeCircle04()方法,輸出的結果信息如下所示。

調用了postProcessBeforeInitialization方法,beanName = animalConfig, bean = io.mykit.spring.plugins.register.config.AnimalConfig$$EnhancerBySpringCGLIB$$b045438a@1ed1993a
調用了postProcessAfterInitialization,beanName = animalConfig, bean = io.mykit.spring.plugins.register.config.AnimalConfig$$EnhancerBySpringCGLIB$$b045438a@1ed1993a
Cat類的構造方法...
調用了postProcessBeforeInitialization方法,beanName = cat, bean = io.mykit.spring.plugins.register.bean.Cat@36c88a32
Cat的postConstruct()方法...
Cat的init()方法...
調用了postProcessAfterInitialization,beanName = cat, bean = io.mykit.spring.plugins.register.bean.Cat@36c88a32
Cat的preDestroy()方法...
Cat的destroy()方法...

BeanPostProcessor後置處理器作用

後置處理器用於bean對象初始化前後進行邏輯增強。spring提供了BeanPostProcessor的很多實現類,例如AutowiredAnnotationBeanPostProcessor用於@Autowired註解的實現,AnnotationAwareAspectJAutoProxyCreator用於SpringAOP的動態代理等等。

除此之外,我們還可以自定義BeanPostProcessor的實現類,在其中寫入需要的邏輯。下面以AnnotationAwareAspectJAutoProxyCreator爲例,說明後置處理器是怎樣工作的。我們都知道springAOP的實現原理是動態代理,最終放入容器的是代理類的對象,而不是bean本身的對象,那麼spring是什麼時候做到這一步的?就是在AnnotationAwareAspectJAutoProxyCreator後置處理器的postProcessAfterInitialization方法,即bean對象初始化完成之後,後置處理器會判斷該bean是否註冊了切面,如果是,則生成代理對象注入容器。Spring中的關鍵代碼如下所示。

/**
  * Create a proxy with the configured interceptors if the bean is
  * identified as one to proxy by the subclass.
  * @see #getAdvicesAndAdvisorsForBean
  */
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章