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);
}
}