Spring原始碼分析:BeanPostProcessor原理

農碼一生發表於2019-01-19

BeanPostProcessor即,Bean的後置處理器,它的作用就是在Bean的初始化方法前跟後進行攔截處理。我們都知道,要想在Bean的初始化方法前後進行工作,那必須在Bean例項建立完成之後,init方法執行之前,後置處理器就已經在容器中了,所以我們來到向容器中新增後置處理器的類AbstractApplicationContext,其中refresh()中的registerBeanPostProcessors(beanFactory)就是首先向容器中註冊我們所需要的所有後置處理器。如何註冊後置處理器我們暫不作分析,著重說一下,後置處理器是如何工作的。

程式碼實現

實現類:

@Component
public class BeanPostProcessorImpl implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 返回一個傳過來的物件
        // 在初始化方法呼叫之前進行後置處理工作
        // 什麼時候呼叫呢?在init-method方法之前就呼叫了
        System.out.println("postProcessBeforeInitialization======" + beanName + "======" + bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization======" + beanName + "======" + bean);
        return bean;
    }

}

配置類:

@Configuration
@ComponentScan("com.nmys.story.springCore.springioc.beanpostprocessor_")
public class Config01 {

    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Train train(){
        return new Train();
    }

}

實體類:

/**
 * @author 70KG
 * @Title: Train
 * @Description:
 * @date 2018/7/23下午11:31
 * @From www.nmyswls.com
 */
public class Train {

    private String name = "火車";

    private Integer length = 150;

    public Train() {
        System.out.println("Train構造方法執行。。。。。。");
    }


    public void init() {
        System.out.println("Train的init方法執行。。。。。。");
    }

    public void destroy() {
        System.out.println("Train的destroy方法執行。。。。。。");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getLength() {
        return length;
    }

    public void setLength(Integer length) {
        this.length = length;
    }
}

測試類:

public class Test01 {
    @Test
    public void test() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Config01.class);
        ac.close();
    }
}

列印結果:

Train構造方法執行。。。。。。
postProcessBeforeInitialization======train======com.nmys.story.springCore.springioc.beanpostprocessor_.Train@5aa9e4eb
Train的init方法執行。。。。。。
postProcessAfterInitialization======train======com.nmys.story.springCore.springioc.beanpostprocessor_.Train@5aa9e4eb
Train的destroy方法執行。。。。。。

結果分析:

首先Train構造方法執行建立物件,然後執行了後置處理器的Before方法,然後才呼叫init方法,init方法執行完成,再執行後置處理器的After方法,最後容器關閉執行銷燬方法。

BeanPostProcessor原理分析

AnnotationConfigApplicationContext構造方法中的refresh();
-> AbstractApplicationContext550行finishBeanFactoryInitialization(beanFactory);完成剩餘Bean的初始化工作
-> AbstractApplicationContext869行beanFactory.preInstantiateSingletons();
-> DefaultListableBeanFactory760行getBean(beanName);
-> AbstractBeanFactory317行createBean(beanName, mbd, args);
-> AbstractAutowireCapableBeanFactory503行doCreateBean(beanName, mbdToUse, args);
-> AbstractAutowireCapableBeanFactory580行populateBean(beanName, mbd, instanceWrapper);在執行初始化之前,首先給例項賦值
-> AbstractAutowireCapableBeanFactory581行exposedObject = initializeBean(beanName, exposedObject, mbd);準備執行初始化方法
-> AbstractAutowireCapableBeanFactory1700行wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
-> AbstractAutowireCapableBeanFactory1704行invokeInitMethods(beanName, wrappedBean, mbd);
-> AbstractAutowireCapableBeanFactory1712行wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

分析AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforeInitialization方法:

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}
  1. 首先獲取到所有的後置處理器getBeanPostProcessors()
  2. 在for迴圈中依次呼叫後置處理器的方法beanProcessor.postProcessBeforeInitialization(result, beanName);
  3. 進入postProcessBeforeInitialization方法(這個方法必須在debug過程中才可以進入)
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
    AccessControlContext acc = null;
    if (System.getSecurityManager() != null &&
            (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                    bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                    bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
        acc = this.applicationContext.getBeanFactory().getAccessControlContext();
    }
    if (acc != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareInterfaces(bean);
            return null;
        }, acc);
    }
    else {
        invokeAwareInterfaces(bean);
    }
    return bean;
}

<!–more–>

private void invokeAwareInterfaces(Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof EnvironmentAware) {
            ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
        }
        if (bean instanceof EmbeddedValueResolverAware) {
            ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
        }
        if (bean instanceof ResourceLoaderAware) {
            ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
        }
        if (bean instanceof ApplicationEventPublisherAware) {
            ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
        }
        if (bean instanceof MessageSourceAware) {
            ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
        }
        if (bean instanceof ApplicationContextAware) {
            ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
        }
    }
}
  1. 來到ApplicationContextAwareProcessor類的79行,首先判斷此bean是不是各種的Aware,如果是它列舉的那幾個Aware就獲取Bean工廠的許可權,可以向容器中匯入相關的上下文環境,目的是為了Bean例項能夠獲取到相關的上下文,如果不是(顯然它也不是)它列舉的幾個Aware,那就呼叫invokeAwareInterfaces(bean),向容器中新增相關介面的上下文環境,顯然我們自己的實現類也不屬於Aware介面,所以這個處理結果直接將Bean返回,不做任何處理。ok,這樣初始化之前的方法就分析完了,初始化之後的方法跟前面的流程一模一樣。

總結

BeanPostProcessor就是在Bean例項建立之後,在進行populateBean賦值之後,init初始化方法之前進行一次呼叫,init方法之後進行一次呼叫,這樣一來,整個Bean的生命週期,全部掌控在了Spring之下,包括Bean例項建立new Instance(),賦值前後populateBean(),初始化前後init(),銷燬前後destroy()。從此Bean便身不由己了。

相關文章