有時候,我們希望在Spring IoC容器初始化受管Bean之前、屬性設(shè)置之后對該Bean先做一些預(yù)處理,或者在容器銷毀受管Bean之前自己釋放資源。那么該如何實現(xiàn)呢?Spring IoC為我們提供了多種方法來實現(xiàn)受管Bean的預(yù)處理和后處理。
在Spring中定義了BeanPostProcessors接口,代碼如下:
- package org.springframework.beans.factory.config;
-
- import org.springframework.beans.BeansException;
-
- public interface BeanPostProcessor {
-
- Object postProcessBeforeInitialization(Object bean,String BeanName)throws BeansException;
-
- Object postProcessAfterInitialization(Object bean,String BeanName)throws BeansException;
- }
如果這個接口的某個實現(xiàn)類被注冊到某個容器,那么該容器的每個受管Bean在調(diào)用初始化方法之前,都會獲得該接口實現(xiàn)類的一個回調(diào)。容器調(diào)用接口定義的方法時會將該受管Bean的實例和名字通過參數(shù)傳入方法,進(jìn)過處理后通過方法的返回值返回給容器。根據(jù)這個原理,我們就可以很輕松的自定義受管Bean。
上面提到過,要使用BeanPostProcessor回調(diào),就必須先在容器中注冊實現(xiàn)該接口的類,那么如何注冊呢?BeanFactory和ApplicationContext容器的注冊方式不大一樣:若使用BeanFactory,則必須要顯示的調(diào)用其addBeanPostProcessor()方法進(jìn)行注冊,參數(shù)為BeanPostProcessor實現(xiàn)類的實例;如果是使用ApplicationContext,那么容器會在配置文件在中自動尋找實現(xiàn)了BeanPostProcessor接口的Bean,然后自動注冊,我們要做的只是配置一個BeanPostProcessor實現(xiàn)類的Bean就可以了。
注意,假如我們使用了多個的BeanPostProcessor的實現(xiàn)類,那么如何確定處理順序呢?其實只要實現(xiàn)Ordered接口,設(shè)置order屬性就可以很輕松的確定不同實現(xiàn)類的處理順序了。
例程3.5展示了如何使用BeanPostProcessor回調(diào)接口。創(chuàng)建Java工程,為其添加Spring開發(fā)能力后,創(chuàng)建ioc.test包。再創(chuàng)建一個名字為Animal的Bean,添加name、age成員和speak()方法。代碼如下:
- package ioc.test;
-
- public class Animal {
-
- private String name;
-
- private int age;
-
- public String speak(){
- return "我的名字是:"+this.name+",年齡是:"+this.age+"!\n";
- }
- //Geter和Seter省略
- }
創(chuàng)建一個BeanPost類,實現(xiàn)BeanPostProcessor接口。在其postProcessAfterInitialization()方法中修改通過參數(shù)傳入的受管Bean,然后返回。由于它處理容器中的每一個Bean,因此在修改前,應(yīng)判斷Bean是否為我們要處理的Bean??梢酝ㄟ^傳入Bean的類型判定,也可以通過傳入Bean的名字判定。代碼如下:
- package ioc.test;
-
- //Import省略
-
- public class BeanPost implements BeanPostProcessor {
-
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
-
- System.out.println("BeanPostProcessor.postProcessAfterInitialization 正在預(yù)處理!");
-
- if ((bean instanceof Animal)) {
-
- Animal animal = (Animal) bean;
-
- animal.setAge(50);
-
- animal.setName("猴子");
-
- return bean;
-
- }
-
- return bean;
- }
-
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
-
- System.out.println("BeanPostProcessor.postProcessBeforeInitialization 正在預(yù)處理!");
-
- return bean;
-
- }
- }
定義好Animal Bean,為其屬性隨便注入一個值,再定義一個Bean,class為BeanPost類。代碼如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans
- xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
- <bean id="animal" class="ioc.test.Animal">
- <property name="age" value="5"></property>
- <property name="name" value="豬"></property>
- </bean>
- <bean id="beanPost" class="ioc.test.BeanPost"></bean>
- </beans>
最后創(chuàng)建TestMain類輸出結(jié)果,代碼如下:
- package ioc.test;
-
- //Import省略
-
- public class TestMain {
-
- public static void main(String[] args) {
-
- ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
- Animal animal = (Animal)ac.getBean("animal");
- System.out.println(animal.speak());
-
- }
- }
運(yùn)行后輸出結(jié)果如下:
運(yùn)行結(jié)果
可以看到,輸出結(jié)果并不是我們在配置文件中注入的值,這說明BeanPost已經(jīng)成功的修改了目標(biāo)Bean。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點擊舉報。