Spring動態替換Bean
阿新 • • 發佈:2018-11-21
BeanPostProcessor是建立每個類時都會去執行的一個介面,postProcessBeforeInitialization是在類初始化之前呼叫的一個方法,建立的物件的引用會指向改方法的返回值物件。呼叫過程示例如下:
ClassA classA = new ClassA();
classA = postProcessBeforeInitialization(classA, "classA");
所以我們可以通過該方法就可以實現動態替換我們的bean。
package com.example.hellododo.data; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.stereotype.Component; /** * @author Liangzhifeng * date: 2018/9/4 */ @Slf4j @Component public class LocalProcessor implements BeanPostProcessor { @Autowired private DefaultListableBeanFactory defaultListableBeanFactory; private String targetBeanName = "test22"; @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (StringUtils.endsWithIgnoreCase(beanName, targetBeanName)) { boolean containsBean = defaultListableBeanFactory.containsBean(targetBeanName); if (containsBean) { //移除bean的定義和例項 defaultListableBeanFactory.removeBeanDefinition(targetBeanName); } //註冊新的bean定義和例項 defaultListableBeanFactory.registerBeanDefinition(targetBeanName, BeanDefinitionBuilder.genericBeanDefinition(Test55.class).getBeanDefinition()); bean = null; return new Test55(); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }
在事件監聽器中,分別注入和獲取Bean物件。分別列印兩個物件的類名,可以看到兩個類名都是com.example.hellododo.data.Test55
package com.example.hellododo.data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.stereotype.Component; /** * @author Liangzhifeng * date: 2018/9/12 */ @Slf4j @Component public class LocalEventListener implements ApplicationListener<ContextRefreshedEvent> { @Autowired private DefaultListableBeanFactory defaultListableBeanFactory; private boolean doFist = true; @Autowired private Test22 test22; @Override public void onApplicationEvent(ContextRefreshedEvent event) { Test22 bean = defaultListableBeanFactory.getBean(Test22.class); if (doFist) { if (bean != null) { log.info("autowiredClassName={}, beanClassName={}", test22.getClass().getName(), bean.getClass().getName()); doFist = false; } } } }
package com.example.hellododo.data;
import lombok.Data;
/**
* @author Liangzhifeng
* date: 2018/9/6
*/
@Data
public class Test {
private String data;
}
@Component package com.example.hellododo.data; import org.springframework.stereotype.Component; /** * @author Liangzhifeng * date: 2018/9/6 */ @Component public class Test22 extends Test{ }
package com.example.hellododo.data;
/**
* @author Liangzhifeng
* date: 2018/9/6
*/
public class Test55 extends Test22{
}