spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(01)

在spring中beanPostProcessor絕對是開天闢地的產物,給了程序員不少自主權,beanPostProcessor即常說的bean後置處理器。程序員

1、概覽

先來講下InstantiationAwareBeanPostProcessor,這個後置處理器是BeanPostProcessor的子接口,繼承自BeanPostProcessor,先看下BeanPostProcessor中的方法,spring

再看下InstantiationAwareBeanPostProcessor中的方法,app

可見InstantiationAwareBeanPostProcessor擴展了BeanPostProcessor接口,而且新增了4個方法,今天先看postProcessAfterInstantiation方法,ide

default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }

改方法有默認的返回值爲true。post

2、詳述

InstantiationAwareBeanPostProcessor中的postProcessAfterInstantiation方法的做用是什麼那,用在什麼地方。在看spring源碼的時候看到屬性注入這段代碼,其中屬性注入是在populateBean方法中完成,在此方法中便出現了postProcessAfterInstatiation方法的調用,這裏只貼出populateBean方法中和這塊有關係的代碼,測試

boolean continueWithPropertyPopulation = true;
 //調用beanFactory中已註冊的beanPostProcessors即bean後置處理器,判斷是否爲InstantiationAwareBeanPostProcessor的類型,若是是執行postProcessAfterInstantiation
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//若是返回值爲false纔會進到下面的賦值操做,從而下方的1處纔會爲true,則屬性注入纔會中斷
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } //1 if (!continueWithPropertyPopulation) { return; }

上面這段邏輯就是來循環已經註冊的beanPostProcessor,找到是InstantiationAwareBeanPostProcessor的類型,並執行其postProcessAfterInstantiation方法,經過查看已註冊的beanPostProcessor發現其返回值均爲true,經過上面的分析,只有postProcessAfterInstantiation方法返回false,populateBean方法纔會返回,屬性注入纔會中斷,即不會注入值。this

怎麼才能保證postProcessAfterInstantiation方法返回false那,這裏只有本身向spring註冊一個InstantiationAwareBeanPostProcessor的後置處理器,下面是個人一個後置處理器,spa

package cn.com.my.test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        // TODO Auto-generated method stub
        System.out.println("beanName:"+beanName);
        if("userService".equals(beanName)) {
            return false;
        }
        return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
    }
}

自定義的beanPostProcessor僅實現了postProcessAfterInstantiation方法,上面的代碼邏輯中,能夠看到只有beanName爲userService的時候,改方法纔會返回false,其餘狀況下調用的接口方法,返回默認值true。code

下面看個人測試類,blog

package cn.com.my.test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(Config.class);
        
        UserService us=ac.getBean(UserService.class);
        System.out.println("us.roleService:"+us.getRoleService());
    }

}

下面是個人UserService類,

package cn.com.my.test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class UserService {

    @Autowired
    private RoleService roleService;
    
    

    public RoleService getRoleService() {
        return roleService;
    }

    public void setRoleService(RoleService roleService) {
        this.roleService = roleService;
    }
}

從UserService類中,能夠看出有一個加了註解的roleService屬性,正常狀況下會自動注入改屬性,但在我自定義的beanPostProcessor以後,看下面的結果

神奇的事情,發生了us.roleService的屬性返回的null。

這是爲何那,咱們再看populateBean中的這段代碼,

boolean continueWithPropertyPopulation = true;
        //調用beanPostProcessors即bean後置處理器,
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }

        if (!continueWithPropertyPopulation) {
            return;
        }

因爲,咱們向beanFactory中註冊了一個beanPostProcessor,因此這裏循環的時候確定會執行個人postProcessAfterInstantiation後置處理器,而我在後置處理器中進行了判斷,即在給beanName爲userService進行屬性注入的時候postProcessAfterInstantiation方法會返回false,那麼上面的continueWithPropertyPopulation便爲false,致使會進入到下面的if,方法直接返回,屬性注入便會停止,因此UserService類中的roleService的值爲null。

3、適用場合

何時須要實現InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法那,若是不想使用spring的自動注入(前提是已經使用了@Autowired註解),則對於特殊的bean則能夠註冊一個beanPostProcessor使其不進行注入,使用本身的方式進行注入。

 

原創不易,有不當之處,歡迎指正,謝謝!

相關文章
相關標籤/搜索