無狀態 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:
1
2
3
4
|
<bean id= "book" class = "net.deniro.spring4.bean.book" p:name= "面紗" > </bean> |
bean author 的 scope 設置為 prototype。
book 類實現 beanfactoryaware 接口:
1
2
3
4
5
6
7
8
9
10
|
public class book implements beanfactoryaware { ... @override public void setbeanfactory(beanfactory beanfactory) throws beansexception { this .factory = beanfactory; } public author getprototypeauthor() { return (author) factory.getbean( "author" ); } } |
單元測試:
1
2
3
4
5
6
7
8
9
10
11
12
|
applicationcontext context; @beforemethod public void setup() throws exception { context = new classpathxmlapplicationcontext( "beans5-5.xml" ); } @test public 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 接口:
1
2
3
|
public interface bookinterface { author getauthor(); } |
xml 配置:
1
2
3
4
5
6
7
|
<!-- 方法注入--> <bean id= "author" class = "net.deniro.spring4.bean.author" scope= "prototype" p:name= "毛姆" /> <bean id= "book2" class = "net.deniro.spring4.bean.bookinterface" > <lookup-method name= "getauthor" bean= "author" /> </bean> |
單元測試:
1
2
3
|
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() 方法,用于獲取書名:
1
2
3
4
5
6
7
|
/** * 書名 */ private string name; public string getname() { return name; } |
我們現在新建一個 bean,它實現了 methodreplacer 接口,用于替換 book 中的 getname() 方法:
1
2
3
4
5
6
|
public class book4 implements methodreplacer { @override public object reimplement(object obj, method method, object[] args) throws throwable { return "活著" ; } } |
配置:
1
2
3
4
5
|
<bean id= "book3" class = "net.deniro.spring4.bean.book" p:name= "燦爛千陽" > <replaced-method name= "getname" replacer= "book4" /> </bean> <bean id= "book4" class = "net.deniro.spring4.bean.book4" /> |
測試:
1
2
|
book book= (book) context.getbean( "book3" ); assertequals( "活著" , book.getname()); |
總結
以上所述是小編給大家介紹的spring 框架中注入或替換方法實現,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復大家的!
原文鏈接:https://www.jianshu.com/p/c370d71432e0