Spring擴展之三:BeanPostProcessor接口


BeanPostProcessor: Bean初始化前后回調。

InstantiationAwareBeanPostProcessor:Bean實例化前后回調。

SmartInstantiationAwareBeanPostProcessor:Bean類型,構造器,以及對Bean的引用回調。

MergedBeanDefinitionPostProcessor:合並Bean Definition后的回調。

DestructionAwareBeanPostProcessor:Bean銷毀前的回調。

InitializingBean:自定義初始化方法。

 

BeanPostProcessor

1.介紹

允許自定義修改新的bean實例的工廠鈎子函數,例如:檢查標記接口或使用代理包裝bean。

BPP(Bean Post Processor) Bean是一種特殊的Bean,它是在其他任何Bean之前創建並與新創建的bean交互。

通常,在postProcessBeforeInitialization方法中處理標記器接口,而在postProcessAfterInitialization方法中處理bean。

ApplicationContext可以在其bean定義中自動檢測BeanPostProcessor bean,並將這些后處理器應用於隨后創建的任何bean。

一個普通的BeanFactory允許以編程方式注冊后處理器,並將其應用於通過Bean工廠創建的所有Bean。

主要是處理Bean初始化之前以及初始化之后的回調。

先執行的是postProcessBeforeInitialization,然后是afterPropertiesSet,然后是init-method,然后是postProcessAfterInitialization。

public interface BeanPostProcessor {
    /**
     * 在任何bean初始化回調之前(例如InitializingBean的afterPropertiesSet或自定義init-method)之前,
     * 將此BeanPostProcessor應用於給定的新bean實例。
     * 返回的Bean實例可能是原始實例的包裝。
     * 默認實現按原樣返回給定的 bean。
     */
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
    /**
     * 在任何bean初始化回調之后(例如InitializingBean的afterPropertiesSet或自定義init-method)之后,
     * 將此BeanPostProcessor應用於給定的新bean實例。
     * 如果是FactoryBean,則將為FactoryBean實例和由FactoryBean創建的對象(從Spring 2.0開始)調用此回調。
     * 可以通過FactoryBean檢查相應bean實例來決定是應用到FactoryBean還是FactoryBean創建的對象,還是兩者都應用。
     * 返回的Bean實例可能是原始實例的包裝。
     * 默認實現按原樣返回給定的 bean。
     */
    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

2.使用

//注冊方式一
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
   // 傳入beanFactory
    private final BeanFactory beanFactory;
    
    //注冊方式二
    public CustomBeanPostProcessor(BeanFactory beanFactory) {
        System.out.println("CustomBeanPostProcessor 實例化......");
        this.beanFactory = beanFactory;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("spring中bean實例:" + beanName + " 初始化之前處理......");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("spring中bean實例:" + beanName + " 初始化之后處理......");
        if ("person".equals(beanName)){
            Field[] declaredFields = bean.getClass().getDeclaredFields();
            for (Field declaredField : declaredFields) {
                if ("name".equals(declaredField.getName())){
                    try {
                        //修改對象的屬性
                        declaredField.setAccessible(true);
                        declaredField.set(bean,"哈哈哈");
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return bean;
    }
}
// 注冊方式二
// 提示信息: is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
// 對於返回Spring BeanFactoryPostProcessor(BFPP)類型或者BeanPostProcessor(BPP)類型的@Bean方法,必須特別注意。 
// 因為BFPP對象必須在容器生命周期的早期實例化,所以它們會干擾@Configuration類中的@Autowired,@ Value和@PostConstruct之類的注釋的處理。 
// 為了避免這些生命周期問題,請將BFPP或BPP返回的@Bean方法標記為static
@Bean
public static CustomBeanPostProcessor customBeanPostProcessor(){
    return new CustomBeanPostProcessor(null);
}
//注冊方式三
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));

3.注意

  • BeanPostProcessor依賴的bean,不會執行BeanPostProcessor的方法,因為所依賴的Bean需要在BeanPostProcessor之前創建完成。
  • BeanPostProcessor以及依賴的bean無法使用AOP。
  • 當使用ConfigurableBeanFactory接口的addBeanPostProcessor方法手動添加BeanPostProcessor時,只能作用於那些延遲加載的Bean或非單例bean。
  • 當使用addBeanPostProcessor方式添加的BeanPostProcessor,Ordered接口的作用將失效,而是以注冊的順序執行。
  • 在使用@Bean聲明工廠方法返回BeanPostProcessor實現類對象時,返回值必須是BeanPostProcessor類型,或者更低級的類型。

4.注冊點

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        prepareRefresh();
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        prepareBeanFactory(beanFactory);
        try {
            postProcessBeanFactory(beanFactory);
            // 實例化並調用所有注冊的BeanFactoryPostProcessor bean,必須在單例實例化之前調用
            invokeBeanFactoryPostProcessors(beanFactory);
            // 注冊攔截bean創建的BeanPostProcessor處理器.
 registerBeanPostProcessors(beanFactory);
            initMessageSource();
            initApplicationEventMulticaster();
            onRefresh();
            registerListeners();
            finishBeanFactoryInitialization(beanFactory);
            finishRefresh();
        }
        ...
    }
}

5.觸發點

InstantiationAwareBeanPostProcessor

1.介紹

BeanPostProcessor的子接口,在繼承BeanPostProcessor的基礎上添加了實例化之前,以及實例化之后的回調,但設置了顯式屬性或發生自動裝配之前的回調。

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
    /*
     * 實例化bean之前回調,如果該方法返回null,后面的方法都正常執行;
     * 如果返回一個非null對象,則bean創建過程將被短路,將直接執行postProcessAfterInitialization方法,(實例化之后和初始化之前都不執行)
     */
    @Nullable
    default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }

    /**
     * 在實例化bean之后但在發生Spring屬性填充(通過顯式屬性或自動裝配)之前回調。
     */
    default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }

    /**
     * 在將屬性值應用於bean之前回調
     */
    @Nullable
    default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
            throws BeansException {
        return null;
    }

    // API不推薦使用
    @Deprecated
    @Nullable
    default PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        return pvs;
    }
}

2.觸發點

SmartInstantiationAwareBeanPostProcessor

1.介紹

InstantiationAwareBeanPostProcessor的子接口,在繼承InstantiationAwareBeanPostProcessor的基礎上添加了返回獲取目標對象的類型,構造器,以及對Bean的引用回調。

public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {

    // 確定給定bean的類型。
    @Nullable
    default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }
    // 確定要用於給定bean的候選構造函數。
    @Nullable
    default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
            throws BeansException {
        return null;
    }
    // 獲取要提前暴露的bean的引用,用來支持單例對象的循環引用(一般是bean自身,如果是代理對象則需要取用代理引用)
    default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

2.觸發點

InstantiationAwareBeanPostProcessorAdapter

1.介紹

實現了SmartInstantiationAwareBeanPostProcessor接口,而SmartInstantiationAwareBeanPostProcessor接口繼承InstantiationAwareBeanPostProcessor接口,InstantiationAwareBeanPostProcessor接口又繼承BeanPostProcessor接口;

所以InstantiationAwareBeanPostProcessorAdapter是這些接口的合集。

public abstract class InstantiationAwareBeanPostProcessorAdapter implements SmartInstantiationAwareBeanPostProcessor {
    // 確定給定bean的類型。
    @Override
    @Nullable
    public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }
    // 確定給定bean的候選構造函數。
    @Override
    @Nullable
    public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }
    // 獲取要提前暴露的bean的引用,用來支持單例對象的循環引用(一般是bean自身,如果是代理對象則需要取用代理引用)
    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        return bean;
    }
    // bean實例化之前回調
    @Override
    @Nullable
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }
    // bean實例化之后回調
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }
    // 在將屬性值應用於bean之前回調
    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
            throws BeansException {
        return null;
    }
    // API不推薦使用,廢棄
    @Deprecated
    @Override
    public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        return pvs;
    }
    // bean初始化之前回調
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
    // bean初始化之后回調
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

MergedBeanDefinitionPostProcessor

1.介紹

BeanPostProcessor的子接口,在繼承BeanPostProcessor的基礎上添加了對合並Bean Definition后的回調。

public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
    // 對指定bean的給定合並bean定義進行后處理
    void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

    // 重新設置指定名稱的Bean定義
    default void resetBeanDefinition(String beanName) {
    }
}

2.說明

例如:AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor

,RequiredAnnotationBeanPostProcessor都是MergedBeanDefinitionPostProcessor的實現

3.觸發點

DestructionAwareBeanPostProcessor

1.介紹

BeanPostProcessor的子接口,在繼承BeanPostProcessor的基礎上添加了對Bean銷毀前的回調。

public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
    // 在銷毀Bean之前進行處理,僅適用於容器完全管理其生命周期的bean,單例和作用域bean。
    void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;

    // 判斷是否需要處理這個對象的銷毀
    default boolean requiresDestruction(Object bean) {
        return true;
    }
}

2.觸發點

InitializingBean

1.介紹

由bean實現的接口,可以插手Bean的初始化過程來實現自定義初始化。

public interface InitializingBean {
    // 自定義初始化
    void afterPropertiesSet() throws Exception;
}

2.觸發點

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
        throws Throwable {
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        ...
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {throw pae.getException();}
        }
        else {
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }
    if (mbd != null && bean.getClass() != NullBean.class) {
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) &&
                !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

 3.注意點

1.Spring提供了兩種自定義初始化Bean的方法,一是實現InitializingBean接口,實現afterPropertiesSet方法,二是在配置文件中同過init-method指定,兩種方式可以同時使用。

2.如果兩個都實現,那只會執行afterPropertiesSet方法。

3.實現InitializingBean接口是直接調用afterPropertiesSet方法,比通過反射調用init-method指定的方法效率相對來說要高點。但是init-method方式消除了對spring的依賴

 

BeanPostProcessor接口調用順序:

  1. SmartInstantiationAwareBeanPostProcessor-predictBeanType:確定給定bean的類型。

  2. SmartInstantiationAwareBeanPostProcessor-getEarlyBeanReference:提前暴露的bean的引用,用來支持單例對象的循環引用。

  3. InstantiationAwareBeanPostProcessor-postProcessBeforeInstantiation:bean實例化之前回調,如果有返回實例則直接跳轉到postProcessAfterInitialization方法。

  4. SmartInstantiationAwareBeanPostProcessor-determineCandidateConstructors:確定給定bean的候選構造函數。

  5. MergedBeanDefinitionPostProcessor-postProcessMergedBeanDefinition:對指定bean的給定合並bean定義進行后處理。

  6. InstantiationAwareBeanPostProcessor-postProcessAfterInstantiation:bean實例化之后回調。

  7. InstantiationAwareBeanPostProcessor-postProcessProperties:將屬性值應用於bean之前回調。

  8. BeanPostProcessor-postProcessBeforeInitialization:bean初始化之前回調。

  9. InitializingBean-afterPropertiesSet:自定義初始化方法。

  10. xml中配置的init-method:xml指定的自定義初始化方法。

  11. BeanPostProcessor-postProcessAfterInitialization:bean初始化之后回調。

  12. DestructionAwareBeanPostProcessor-requiresDestruction:確定給定b​​ean實例是否需要此后處理器銷毀。

  13. DestructionAwareBeanPostProcessor-postProcessBeforeDestruction:銷毀對象前回調。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM