1.通過BeanPostProcessor來自定義bean
(1) BeanPostProcessor用于在容器完成了對bean的實體化,配置及初始化后來實作一些自定義邏輯,它是用于操縱由容器創建的每個bean實體的,即在容器實體化了一個bean后以及該bean的初始化回呼(如InitializingBean.afterPropertiesSet()等)被執行之前,會將這個bean交由BeanPostProcessor來進行處理,通過BeanPostProcessor,我們可以對bean實體進行任何操作,包括忽略掉初始化回呼等,BeanPostProcessor通常用來檢查回呼介面,或用來生成某個bean的代理物件,因此一些Spring AOP的基礎類就被實作為BeanPostProcessor實體,以提供代理物件,如下是簡單使用BeanPostProcessor的一個例子
//讓ExampleA實作3個初始化回呼
public class ExampleA implements InitializingBean {
private String name;
public ExampleA() {
System.out.println("ExampleA的構造方法被呼叫");
System.out.println("----------------------------------------");
}
//這個方法只用于IOC的屬性注入
public void setName(String name) {
System.out.println("IOC對ExampleA的name屬性進行注入,值為:" + name);
System.out.println("----------------------------------------");
this.name = name;
}
//這個方法用于我們自己手動注入
public void setNameInOtherWay(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "ExampleA{" +
"name='" + name + '\'' +
'}';
}
@PostConstruct
public void postConstruct() {
System.out.println("正在執行初始化回呼PostConstruct,此時的ExampleA為:" + this);
this.setNameInOtherWay("zzz2");
System.out.println("執行完畢,此時的ExampleA為:" + this);
System.out.println("----------------------------------------");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("正在執行初始化回呼InitializingBean.afterPropertiesSet,此時的ExampleA為:" + this);
this.setNameInOtherWay("zzz3");
System.out.println("執行完畢,此時的ExampleA為:" + this);
System.out.println("----------------------------------------");
}
public void init() {
System.out.println("正在執行初始化回呼init-method,此時的ExampleA為:" + this);
this.setNameInOtherWay("zzz4");
System.out.println("執行完畢,此時的ExampleA為:" + this);
System.out.println("----------------------------------------");
}
}
//實作BeanPostProcessor,自定義后置處理器來操縱bean實體(注意:需要把我們的自定義處理器注入到容器中),它主要提供了2個方法
public class Processor implements BeanPostProcessor {
/**
* 該方法作用于bean實體創建配置好后,初始化回呼執行前,來自定義一些邏輯
* @param bean 實體化并配置好后的bean
* @param beanName bean的名稱
* @return 自定義操作完成后的bean
* @throws BeansException
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("正在執行postProcessBeforeInitialization,此時的ExampleA為:" + bean);
((ExampleA) bean).setNameInOtherWay("zzz1");
System.out.println("執行完畢,此時的ExampleA為:" + bean);
System.out.println("----------------------------------------");
return bean;
}
/**
* 該方法作用于初始化回呼執行后
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("正在執行postProcessAfterInitialization,此時的ExampleA為:" + bean);
((ExampleA) bean).setNameInOtherWay("zzz5");
System.out.println("執行完畢,此時的ExampleA為:" + bean);
System.out.println("----------------------------------------");
return bean;
}
}
<!-- xml組態檔 -->
<beans ....>
<!-- 開啟注解掃描,否則PostConstruct注解不生效 -->
<context:annotation-config></context:annotation-config>
<bean id="exampleA" init-method="init">
<property name="name" value="https://www.cnblogs.com/shame11/archive/2023/01/09/zzz"></property>
</bean>
<!-- 注意僅僅實作介面是不行的,我們必須把自定義后置處理器注冊成bean,它才會生效 -->
<bean id="processor" ></bean>
</beans>
//啟動容器后,列印結果為
ExampleA的構造方法被呼叫
----------------------------------------
IOC對ExampleA的name屬性進行注入,值為:zzz
----------------------------------------
正在執行postProcessBeforeInitialization,此時的ExampleA為:ExampleA{name='zzz'}
執行完畢,此時的ExampleA為:ExampleA{name='zzz1'}
----------------------------------------
正在執行初始化回呼PostConstruct,此時的ExampleA為:ExampleA{name='zzz1'}
執行完畢,此時的ExampleA為:ExampleA{name='zzz2'}
----------------------------------------
正在執行初始化回呼InitializingBean.afterPropertiesSet,此時的ExampleA為:ExampleA{name='zzz2'}
執行完畢,此時的ExampleA為:ExampleA{name='zzz3'}
----------------------------------------
正在執行初始化回呼init-method,此時的ExampleA為:ExampleA{name='zzz3'}
執行完畢,此時的ExampleA為:ExampleA{name='zzz4'}
----------------------------------------
正在執行postProcessAfterInitialization,此時的ExampleA為:ExampleA{name='zzz4'}
執行完畢,此時的ExampleA為:ExampleA{name='zzz5'}
----------------------------------------
綜上可見,添加了BeanPostProcessor后,bean的初始化流程為:執行bean的建構式 -> IOC進行屬性注入 -> BeanPostProcessor.postProcessBeforeInitialization -> 三大初始化回呼 -> BeanPostProcessor.postProcessAfterInitialization
(2) 我們可以向容器中注入多個自定義BeanPostProcessor,并通過實作Ordered介面來控制這些BeanPostProcessor的執行順序,如下所示
public class ExampleA { }
//讓該自定義后置處理器實作Ordered介面,指定它在所有自定義后置處理器中的執行順序
public class Processor0 implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Order值為0的postProcessBeforeInitialization執行...");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Order值為0的postProcessAfterInitialization執行...");
return bean;
}
@Override
public int getOrder() {
return 0;
}
}
public class Processor1 implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Order值為1的postProcessBeforeInitialization執行...");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Order值為1的postProcessAfterInitialization執行...");
return bean;
}
@Override
public int getOrder() {
return 1;
}
}
<!-- xml組態檔 -->
<beans ....>
<bean id="exampleA" ></bean>
<bean id="processor0" ></bean>
<bean id="processor1" ></bean>
</beans>
//啟動容器,輸出如下
Order值為0的postProcessBeforeInitialization執行...
Order值為1的postProcessBeforeInitialization執行...
Order值為0的postProcessAfterInitialization執行...
Order值為1的postProcessAfterInitialization執行...
由上可見,getOrder回傳值越小,自定義的后置處理器就越先執行
(3) 在一個容器中注入了一個BeanPostProcessor,那么該BeanPostProcessor僅對該容器中的bean進行后置處理,例如,即父容器中的BeanPostProcessor不會作用于子容器中的bean
(4) BeanPostProcessor作用于bean實體化并配置好了之后,換句話說,在BeanPostProcessor起作用時,bean實體已經存在了,因此,如果我們想要修改bean的配置元資料(即BeanDefinition,此時的bean還未被創建),則需要實作BeanFactoryPostProcessor介面,它與BeanPostProcessor類似,只不過作用時機不同
未完待續...
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/541559.html
標籤:其他
