1. 程式人生 > >Spring動態 注入/刪除 Bean

Spring動態 注入/刪除 Bean

我們通過getBean來獲得物件,但這些物件都是事先定義好的,我們有時候要在程式中動態的加入物件.因為如果採用配置檔案或者註解,我們要加入物件的話,還要重啟服務,如果我們想要避免這一情況就得采用動態處理bean,包括:動態注入,動態刪除。

1 動態注入bean思路;

在具體進行程式碼實現的時候,我們要知道,Spring管理bean的物件是BeanFactory,具體的是DefaultListableBeanFactory,在這個類當中有一個注入bean的方法:registerBeanDefinition,在呼叫registerBeanDefinition方法時,需要BeanDefinition引數,那麼這個引數怎麼獲取呢?Spring提供了BeanDefinitionBuilder

可以構建一個BeanDefinition,那麼我們的問題就是如何獲取BeanFactory了,這個就很簡單了,只要獲取到ApplicationContext物件即可獲取到BeanFacory了。

2. 動態注入實現程式碼;

綜上所述,如果我們要編寫一個簡單裡的例子的話,那麼分以個幾個步驟進行編碼即可進行動態注入了:

  1. 獲取ApplicationContext;
  2. 通過ApplicationContext獲取到BeanFacotory;
  3. 通過BeanDefinitionBuilder構建BeanDefiniton;
  4. 呼叫beanFactory的registerBeanDefinition注入beanDefinition;
  5. 使用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一樣的話,後面注入的會覆蓋前面的。

  1. 第一種情況:beanName一樣的程式碼:
beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(TestService.class);

beanDefinitionBuilder.addPropertyValue("name","李四");

defaultListableBeanFactory.registerBeanDefinition("testService", beanDefinitionBuilder.getBeanDefinition());

執行看控制檯:

動態載入bean,name=李四
  1. 第二種情況: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");