Spring 框架中注入或替換方法實(shí)現(xiàn)
無狀態(tài) Bean 的作用域是 singleton 單實(shí)例,如果我們向 singleton 的 Bean A 注入 prototype 的 Bean B,并希望每次調(diào)用 Bean A 的 getBeanB() 時都能返回一個新的 Bean B ,這樣的要求使用傳統(tǒng)的注入方式是無法實(shí)現(xiàn)的 。 因?yàn)?singleton 的 Bean 注入關(guān)聯(lián) Bean 的動作只發(fā)生一次,雖然 Bean B 的作用域是 prototype 類型,但通過 getBeanB() 返回的對象還是最開始注入的那個 bean B。
所以如果希望每次調(diào)用 BeanA 的 getBeanB() 時都能返回一個新的 BeanB 的一種可選的方案是:讓 Bean A 實(shí)現(xiàn) BeanFactoryAware 接口,從而能夠訪問容器,然后以下面這種方式來實(shí)現(xiàn)。
首先配置 XML:
<bean id="author" class="net.deniro.spring4.bean.Author" scope="prototype"/> <bean id="book" class="net.deniro.spring4.bean.Book" p:name="面紗"> </bean>
bean author 的 scope 設(shè)置為 prototype。
Book 類實(shí)現(xiàn) BeanFactoryAware 接口:
public class Book implements BeanFactoryAware { ... @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.factory = beanFactory; } public Author getPrototypeAuthor() { return (Author) factory.getBean("author"); } }
單元測試:
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());
測試結(jié)果
從結(jié)果中可以發(fā)現(xiàn),只有從 BeanFactory 中獲取得到的 Author 實(shí)例是不同的。
這種實(shí)現(xiàn)把應(yīng)用與 Spring 框架綁定在了一起,是否有更好的解決方案呢?有,就是注入方法。
1 注入方法
Spring 容器依賴于 CGLib 庫,所以可以在運(yùn)行期動態(tài)操作 Class 的字節(jié)碼,比如動態(tài)地創(chuàng)建 Bean 的子類或?qū)崿F(xiàn)類。
BookInterface 接口:
public interface BookInterface { Author getAuthor(); }
XML 配置:
<!-- 方法注入--> <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>
單元測試:
BookInterface book= (BookInterface) context.getBean("book2"); Assert.assertEquals("毛姆",book.getAuthor().getName()); Assert.assertTrue(book.getAuthor().hashCode()!=book.getAuthor().hashCode());
通過這種配置方式,就可以為接口提供動態(tài)實(shí)現(xiàn)啦,而且這樣返回的 Bean 都是新的實(shí)例。
所以,如果希望在一個 singleton Bean 中獲取一個 prototype Bean 時,就可以使用 lookup 來實(shí)現(xiàn)注入方法。
2 替換方法
在 Spring 中,可以使用某個 Bean 的方法去替換另一個 Bean 的方法。
假設(shè) Book 中有一個 getName() 方法,用于獲取書名:
/** * 書名 */ private String name; public String getName() { return name; }
我們現(xiàn)在新建一個 Bean,它實(shí)現(xiàn)了 MethodReplacer 接口,用于替換 Book 中的 getName() 方法:
public class Book4 implements MethodReplacer { @Override public Object reimplement(Object obj, Method method, Object[] args) throws Throwable { return "活著"; } }
配置:
<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"/>
測試:
Book book= (Book) context.getBean("book3"); assertEquals("活著", book.getName());
總結(jié)
以上所述是小編給大家介紹的Spring 框架中注入或替換方法實(shí)現(xiàn),希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復(fù)大家的!
相關(guān)文章
解決java maven項(xiàng)目找不到j(luò)console-1.8.0.jar和tools-1.8.0.jar包問題
這篇文章主要介紹了解決java maven項(xiàng)目找不到j(luò)console-1.8.0.jar和tools-1.8.0.jar包問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08Spring MVC學(xué)習(xí)教程之RequestMappingHandlerMapping匹配
這篇文章主要給大家介紹了關(guān)于Spring MVC學(xué)習(xí)教程之RequestMappingHandlerMapping匹配的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-11-11JavaWeb ServletContext基礎(chǔ)與應(yīng)用詳細(xì)講解
ServletConfig對象,叫Servlet配置對象。主要用于加載配置文件的初始化參數(shù)。我們知道一個Web應(yīng)用里面可以有多個servlet,如果現(xiàn)在有一份數(shù)據(jù)需要傳給所有的servlet使用,那么我們就可以使用ServletContext對象了2023-01-01Spring Boot中優(yōu)雅的獲取yml文件工具類
今天小編就為大家分享一篇關(guān)于Spring Boot中優(yōu)雅的獲取yml文件工具類,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12