Spring動態 注入/刪除 Bean
阿新 • • 發佈:2018-12-10
我們通過getBean來獲得物件,但這些物件都是事先定義好的,我們有時候要在程式中動態的加入物件.因為如果採用配置檔案或者註解,我們要加入物件的話,還要重啟服務,如果我們想要避免這一情況就得采用動態處理bean,包括:動態注入,動態刪除。
1 動態注入bean思路;
在具體進行程式碼實現的時候,我們要知道,Spring管理bean的物件是BeanFactory,具體的是DefaultListableBeanFactory
,在這個類當中有一個注入bean的方法:registerBeanDefinition,在呼叫registerBeanDefinition方法時,需要BeanDefinition引數,那麼這個引數怎麼獲取呢?Spring提供了BeanDefinitionBuilder
2. 動態注入實現程式碼;
綜上所述,如果我們要編寫一個簡單裡的例子的話,那麼分以個幾個步驟進行編碼即可進行動態注入了:
- 獲取ApplicationContext;
- 通過ApplicationContext獲取到BeanFacotory;
- 通過BeanDefinitionBuilder構建BeanDefiniton;
- 呼叫beanFactory的registerBeanDefinition注入beanDefinition;
- 使用ApplicationContext.getBean獲取bean進行測試;
我們需要先定義個類進行測試,比如TestService程式碼如下:
package com.kfit.demo.service; public class TestService { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void print(){ System.out.println("動態載入bean,name="+name); } }
那麼下面我們的目標就是動態注入TestService了,根據以上的分析,我們進行編碼,具體程式碼如下:
//獲取context.
ApplicationContext ctx = (ApplicationContext) SpringApplication.run(App.class, args);
//獲取BeanFactory
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory)ctx.getAutowireCapableBeanFactory();
//建立bean資訊
BeanDefinitionBuilderbeanDefinitionBuilder =BeanDefinitionBuilder.genericBeanDefinition(TestService.class);
beanDefinitionBuilder.addPropertyValue("name","張三");
//動態註冊bean
defaultListableBeanFactory.registerBeanDefinition("testService",beanDefinitionBuilder.getBeanDefinition());
//獲取動態註冊的bean
TestService testService =ctx.getBean(TestService.class);
testService.print();
執行程式碼
動態載入bean,name=張三
到這裡,就證明我們的程式碼很成功了。
3 多次注入同一個bean的情況;
多次注入同一個bean的,如果beanName不一樣的話,那麼會產生兩個Bean;如果beanName一樣的話,後面注入的會覆蓋前面的。
- 第一種情況:beanName一樣的程式碼:
beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(TestService.class);
beanDefinitionBuilder.addPropertyValue("name","李四");
defaultListableBeanFactory.registerBeanDefinition("testService", beanDefinitionBuilder.getBeanDefinition());
執行看控制檯:
動態載入bean,name=李四
- 第二種情況:beanName不一樣的程式碼:
beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(TestService.class);
beanDefinitionBuilder.addPropertyValue("name","李四");
defaultListableBeanFactory.registerBeanDefinition("testService1",beanDefinitionBuilder.getBeanDefinition());
TestService testService =ctx.getBean(TestService.class);
testService.print();
此時如果沒有更改別的程式碼直接執行的話,是會報如下錯誤的:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.kfit.demo.service.TestService] is defined: expected single matching bean but found 2: testService1,testService
大體意思就是在按照 byType getBean的時候,找到了兩個bean,這時候就不知道要獲取哪個了,所以在獲取的時候,我們就要使用byName指定我們是要獲取的testService還是testService1,只需要修改一句程式碼:
TestService testService =ctx.getBean("testService");
4 動態刪除;
相對於動態注入,動態刪除就很簡單了,直接奉上程式碼:
//刪除bean.
defaultListableBeanFactory.removeBeanDefinition("testService");