無狀態Bean 的作用域是singleton 單實例,如果我們向singleton 的Bean A 注入prototype 的Bean B,並希望每次調用Bean A 的getBeanB() 時都能返回一個新的Bean B ,這樣的要求使用傳統的注入方式是無法實現的。 因為singleton 的Bean 注入關聯Bean 的動作只發生一次,雖然Bean B 的作用域是prototype 類型,但通過getBeanB() 返回的對像還是最開始注入的那個bean B。
所以如果希望每次調用BeanA 的getBeanB() 時都能返回一個新的BeanB 的一種可選的方案是:讓Bean A 實現BeanFactoryAware 接口,從而能夠訪問容器,然後以下面這種方式來實現。
首先配置XML:
<bean id="author" scope="prototype"/><bean id="book" p:name="面紗"></bean>
bean author 的scope 設置為prototype。
Book 類實現BeanFactoryAware 接口:
public class Book implements BeanFactoryAware { ...@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.factory = beanFactory;}public Author getPrototypeAuthor() { return (Author) factory.getBean("author"); }}單元測試:
ApplicationContext context;@BeforeMethodpublic void setUp() throws Exception { context = new ClassPathXmlApplicationContext("beans5-5.xml");}@Testpublic void test(){ Book book= (Book) context.getBean("book"); System.out.println(book.getAuthor().hashCode()); System.out.println(book.getAuthor().hashCode()); System.out.println(book.getPrototypeAuthor().hashCode()); System.out.println(book.getPrototypeAuthor().hashCode());測試結果
從結果中可以發現,只有從BeanFactory 中獲取得到的Author 實例是不同的。
這種實現把應用與Spring 框架綁定在了一起,是否有更好的解決方案呢?有,就是注入方法。
1 注入方法
Spring 容器依賴於CGLib 庫,所以可以在運行期動態操作Class 的字節碼,比如動態地創建Bean 的子類或實現類。
BookInterface 接口:
public interface BookInterface { Author getAuthor();}XML 配置:
<!-- 方法注入--><bean id="author" scope="prototype" p:name="毛姆" /><bean id="book2"> <lookup-method name="getAuthor" bean="author"/></bean>
單元測試:
BookInterface book= (BookInterface) context.getBean("book2");Assert.assertEquals("毛姆",book.getAuthor().getName());Assert.assertTrue(book.getAuthor().hashCode()!=book.getAuthor().hashCode());通過這種配置方式,就可以為接口提供動態實現啦,而且這樣返回的Bean 都是新的實例。
所以,如果希望在一個singleton Bean 中獲取一個prototype Bean 時,就可以使用lookup 來實現注入方法。
2 替換方法
在Spring 中,可以使用某個Bean 的方法去替換另一個Bean 的方法。
假設Book 中有一個getName() 方法,用於獲取書名:
/** * 書名*/private String name;public String getName() { return name;}我們現在新建一個Bean,它實現了MethodReplacer 接口,用於替換Book 中的getName() 方法:
public class Book4 implements MethodReplacer { @Override public Object reimplement(Object obj, Method method, Object[] args) throws Throwable { return "活著"; }}配置:
<bean id="book3" p:name="燦爛千陽"> <replaced-method name="getName" replacer="book4"/></bean><bean id="book4"/>
測試:
Book book= (Book) context.getBean("book3");assertEquals("活著", book.getName());總結
以上所述是小編給大家介紹的Spring 框架中註入或替換方法實現,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復大家的!