天天看點

Spring源碼解析-10、BeanFactoryPostProcessor 與 BeanPostProcessor

BeanFactoryPostProcessor 介紹

BeanFactoryPostProcessor 可以 用于容器初始化還沒有執行個體化Bean之前讀取Bean的資訊,并作出一些修改。

例如修改Bean的屬性,修改Bean的scope等。

可以同時配置多個BeanFactoryPostProcessor,通過實作Ordered接口來決定執行順序。

BeanFactoryPostProcessor

public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
}
           

Ordered:

public interface Ordered {
    int HIGHEST_PRECEDENCE = -2147483648;
    int LOWEST_PRECEDENCE = 2147483647;

    int getOrder();
}
           

BeanFactoryPostProcessor 使用案例

下面來寫兩個類,實作BeanFactoryPostProcessor和Ordered接口

BeanFactoryPostProcessorTest1:

public class BeanFactoryPostProcessorTest1 implements BeanFactoryPostProcessor ,Ordered {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("BeanFactoryPostProcessorTest1");
    }


    @Override
    public int getOrder() {
        return 2;
    }
}
           

BeanFactoryPostProcessorTest2:

public class BeanFactoryPostProcessorTest2 implements BeanFactoryPostProcessor ,Ordered {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("BeanFactoryPostProcessorTest2");
    }


    @Override
    public int getOrder() {
        return 0;
    }
}
           

bean.xml

<bean class="com.raycloud.dmj.data.utils.BeanFactoryPostProcessorTest1"    />
 <bean class="com.raycloud.dmj.data.utils.BeanFactoryPostProcessorTest2"    />
           

main:

ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
           

輸出:

BeanFactoryPostProcessorTest2

BeanFactoryPostProcessorTest1

發現個有意思的現象,實作了BeanFactoryPostProcessor的類在容器初始化時就會被強制初始化,無論是否設定為多例,或者lazy_init。

通過源碼了解BeanFactoryPostProcessor的執行時機

BeanFactoryPostProcessor在refresh()中的invokeBeanFactoryPostProcessors中執行,

整個過程是這樣的:

1、先周遊執行已經在容器中注冊的BeanFactoryPostProcessor

2、再找BeanDefinition中的BeanFactoryPostProcessor,通過getBean方法執行個體化,并且執行。

源碼太多了,,不貼了

ps:

BeanFactoryPostProcessor 是容器相關的後置處理器,在執行個體化Bean之前執行一次。

BeanPostProcessor 介紹

BeanPostProcessor 與BeanFactoryProcessor是完全不一樣的,BeanPostProcessor是Bean的後置處理器,在Bean的初始化方法[InitializingBean 以及init-method]前後執行。

注意:

可以配置多個BeanPostProcessor,執行的先後順序依舊可以通過Ordered接口來實作。

public interface BeanPostProcessor {
//在Bean的初始化方法之前執行
    Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException;
//在Bean的初始化方法之後執行
    Object postProcessAfterInitialization(Object var1, String var2) throws BeansException;
}
           

BeanPostProcessor 使用

BeanPostProcessorTest1:

public class BeanPostProcessorTest1 implements BeanPostProcessor,Ordered {
    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        System.out.println("BeanPostProcessorTest1 初始化之前");
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println("BeanPostProcessorTest1 初始化之後");
        return o;
    }

    @Override
    public int getOrder() {
        return 1;
    }
}
           

BeanPostProcessorTest2:

public class BeanPostProcessorTest2 implements BeanPostProcessor,Ordered {
    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        System.out.println("BeanPostProcessorTest2 初始化之前");
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println("BeanPostProcessorTest2 初始化之後");
        return o;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
           

user:

public class User implements InitializingBean {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("setName");
        this.name = name;
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean 的 afterPropertiesSet");
    }

    public void initMethod(){
        System.out.println("initMethod");
    }
}
           

bean.xml:

<bean class="com.raycloud.dmj.data.utils.BeanPostProcessorTest1"/>
    <bean class="com.raycloud.dmj.data.utils.BeanPostProcessorTest2"/>

    <bean  class="com.raycloud.dmj.data.utils.User" init-method="initMethod" >
        <property name="name" value="ycf"/>
    </bean>
           

main:

ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
           

輸出:

setName

BeanPostProcessorTest2 初始化之前

BeanPostProcessorTest1 初始化之前

InitializingBean 的 afterPropertiesSet

initMethod

BeanPostProcessorTest2 初始化之後

BeanPostProcessorTest1 初始化之後

通過源碼了解BeanPostProcessor的注冊和執行時機

BeanPostProcessor的注冊時機:

refresh()中的registerBeanPostProcessors()。

主要關注

String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

           

其實就是根據BeanPostProcessor的class去擷取Bean的名稱,然後之後根據名字和class去getBean注冊到容器。

BeanPostProcessor的執行時機:

在擷取Bean的doCreateBean的initializeBean中:

主要關注:

Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = 
			//初始化方法執行前
			applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = 
			//初始化方法執行後
			applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
           

spring中,有内置的一些BeanPostProcessor實作類,例如:

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor:支援@Resource注解的注入

org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor:支援@Required注解的注入

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor:支援@Autowired注解的注入

org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor:支援@PersistenceUnit和@PersistenceContext注解的注入

org.springframework.context.support.ApplicationContextAwareProcessor:用來為bean注入ApplicationContext等容器對象

這些注解類的BeanPostProcessor,在spring配置檔案中,可以通過這樣的配置 <context:component-scan base-package="." /> ,自動進行注冊。(spring通過ComponentScanBeanDefinitionParser類來解析該标簽)

InstantiationAwareBeanPostProcessor介紹

InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口,是以他具有BeanPostProcessor的功能,可以在初始化方法執行前後進行一些操作。

除此之後還多了三個方法:

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
//bean執行個體化前
    Object postProcessBeforeInstantiation(Class<?> var1, String var2) throws BeansException;
//bean執行個體化後
    boolean postProcessAfterInstantiation(Object var1, String var2) throws BeansException;

//修改屬性
    PropertyValues postProcessPropertyValues(PropertyValues var1, PropertyDescriptor[] var2, Object var3, String var4) throws BeansException;
}
           

InstantiationAwareBeanPostProcessor使用

InstantiationAwareBeanPostProcessorTest :

public class InstantiationAwareBeanPostProcessorTest implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> aClass, String s) throws BeansException {
        System.out.println("執行個體化之前");
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object o, String s) throws BeansException {
        System.out.println("執行個體化之後");
        return true;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues propertyValues, PropertyDescriptor[] propertyDescriptors, Object o, String s) throws BeansException {
        System.out.println("修改屬性");
        return propertyValues;
    }

    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        System.out.println("初始化之前");
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println("初始化之後");

        return o;
    }
}
           

user:

public class User implements InitializingBean {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("setName");
        this.name = name;
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean 的 afterPropertiesSet");
    }

    public void initMethod(){
        System.out.println("initMethod");
    }
}
           

bean.xml:

<bean class="com.raycloud.dmj.data.utils.InstantiationAwareBeanPostProcessorTest"/>
    <bean  class="com.raycloud.dmj.data.utils.User" init-method="initMethod" >
        <property name="name" value="ycf"/>
    </bean>
           

main:

ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
           

輸出:

執行個體化之前

執行個體化之後

修改屬性

setName

初始化之前

InitializingBean 的 afterPropertiesSet

initMethod

初始化之後

通過源碼了解InstantiationAwareBeanPostProcessor的執行時機

1、postProcessBeforeInstantiation 執行時機:

執行doCreateBean以前,createBean内:

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}
           

postProcessBeforeInstantiation在Bean執行個體化之前執行,如果傳回不會空,就替換Bean本身傳回出去,有種代理模式的意思。

2、postProcessAfterInstantiation:

如果postProcessBeforeInstantiation傳回不為空的bean,則立馬執行postProcessAfterInstantiation。

否則正常初始化需要的Bean,在屬性設定之前執行。

具體位置在populateBean裡。

3、postProcessPropertyValues:

在postProcessAfterInstantiation傳回true時才會執行,

是在真正設定屬性之前對屬性進行修改。

代碼同樣在populateBean裡。

DestructionAwareBeanPostProcessor介紹

DestructionAwareBeanPostProcessor也是BeanPostProcessor的子接口,除了能在Bean的初始化方法執行前後做一些操作之外,還增加一個額外的方法。

public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
//用于Bean銷毀前做一些操作。
    void postProcessBeforeDestruction(Object var1, String var2) throws BeansException;
}
           

DestructionAwareBeanPostProcessor使用

DestructionAwareBeanPostProcessorTest:

public class DestructionAwareBeanPostProcessorTest implements DestructionAwareBeanPostProcessor {
    @Override
    public void postProcessBeforeDestruction(Object o, String s) throws BeansException {
        System.out.println("銷毀前");

    }

    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        System.out.println("初始化之前");
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println("初始化之後");
        return o;
    }
}
           

user:

public class User implements InitializingBean,DisposableBean {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("setName");
        this.name = name;
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean 的 afterPropertiesSet");
    }

    public void initMethod(){
        System.out.println("initMethod");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean 的 destroy" );
    }

    public void destoryMethod(){
        System.out.println("destoryMethod");
    }
}
           

bean.xml:

<bean class="com.raycloud.dmj.data.utils.DestructionAwareBeanPostProcessorTest"/>
    <bean  class="com.raycloud.dmj.data.utils.User" init-method="initMethod" destroy-method="destoryMethod" >
        <property name="name" value="ycf"/>
    </bean>
           

main:

ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        ((ClassPathXmlApplicationContext) context).close();
           

輸出:

setName

初始化之前

InitializingBean 的 afterPropertiesSet

initMethod

初始化之後

銷毀前

DisposableBean 的 destroy

destoryMethod

通過案例可以看到DestructionAwareBeanPostProcessor的postProcessBeforeDestruction是在銷毀方法執行前做的一些操作。

通過源碼了解DestructionAwareBeanPostProcessor的執行時機

DestructionAwareBeanPostProcessor的postProcessBeforeDestruction在Bean destory的過程中執行,是在Bean的銷毀方法前執行,具體位置是在

DisposableBeanAdapter的destory中,在開頭就能看到,同時也是可以定義多個DestructionAwareBeanPostProcessor。

if (this.beanPostProcessors != null && !this.beanPostProcessors.isEmpty()) {
            Iterator i$ = this.beanPostProcessors.iterator();

            while(i$.hasNext()) {
                DestructionAwareBeanPostProcessor processor = (DestructionAwareBeanPostProcessor)i$.next();
                processor.postProcessBeforeDestruction(this.bean, this.beanName);
            }
        }