spring:如何用代码动态向容器中添加或移除Bean ?
先来看一张类图:
有一个业务接口IFoo,提供了二个实现类:FooA及FooB,默认情况下,FooA使用@Component由Spring自动装配,如果出于某种原因,在运行时需要将IFoo的实现,则FooA换成FooB,可以用代码动态先将FooA的实例从容器中删除,然后再向容器中注入FooB的实例,代码如下:
1、IFoo接口:
package yjmyzz;
import org.springframework.beans.factory.DisposableBean;
public interface IFoo extends DisposableBean {
public void foo();
}
2、 FooA实现
package yjmyzz;
import org.springframework.stereotype.Component;
//注:这里的名称fooA,仅仅只是为了后面演示时看得更清楚,非必需
@Component("fooA")
public class FooA implements IFoo {
public FooA() {
System.out.println("FooA is created!");
}
public void foo() {
System.out.println("FooA.foo()");
}
public void destroy() throws Exception {
System.out.println("FooA.destroy()");
}
}
3、FooB实现
package yjmyzz;
public class FooB implements IFoo {
public FooB() {
System.out.println("FooB is created!");
}
public void foo() {
System.out.println("FooB.foo()");
}
public void destroy() throws Exception {
System.out.println("FooB.destroy()");
}
}
4、测试程序AppDemo
package yjmyzz;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.support.AbstractRefreshableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 演示在运行时,动态向容器中添加、移除Bean
* author:菩提树下的杨过 http://yjmyzz.cnblogs.cm/
*/
public class AppDemo {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
//从context中取出FooA实例
IFoo f = ctx.getBean(IFoo.class);
f.foo();//FooA.foo()
//输出IFoo的Bean基本信息
System.out.println(f.getClass());//class yjmyzz.FooA
String beanName = ctx.getBeanNamesForType(IFoo.class)[0];
System.out.println(beanName);//fooA
System.out.println(ctx.isSingleton(beanName));//true
//销毁FooA实例
removeBean(ctx, beanName);
System.out.println(ctx.containsBean(beanName));//false
System.out.println("------------");
//注入新Bean
beanName = "fooB";
addBean(ctx, beanName, FooB.class);
//取出新实例
f = ctx.getBean(beanName, IFoo.class);
f.foo();
//输出IFoo的Bean基本信息
System.out.println(f.getClass());
beanName = ctx.getBeanNamesForType(IFoo.class)[0];
System.out.println(beanName);//fooB
System.out.println(ctx.isSingleton(beanName));//true
System.out.println("------------");
showAllBeans(ctx);
ctx.close();
}
/**
* 向容器中动态添加Bean
*
* @param ctx
* @param beanName
* @param beanClass
*/
static void addBean(AbstractRefreshableApplicationContext ctx, String beanName, Class beanClass) {
BeanDefinitionRegistry beanDefReg = (DefaultListableBeanFactory) ctx.getBeanFactory();
BeanDefinitionBuilder beanDefBuilder = BeanDefinitionBuilder.genericBeanDefinition(beanClass);
BeanDefinition beanDef = beanDefBuilder.getBeanDefinition();
if (!beanDefReg.containsBeanDefinition(beanName)) {
beanDefReg.registerBeanDefinition(beanName, beanDef);
}
}
/**
* 从容器中移除Bean
*
* @param ctx
* @param beanName
*/
static void removeBean(AbstractRefreshableApplicationContext ctx, String beanName) {
BeanDefinitionRegistry beanDefReg = (DefaultListableBeanFactory) ctx.getBeanFactory();
beanDefReg.getBeanDefinition(beanName);
beanDefReg.removeBeanDefinition(beanName);
}
/**
* 遍历输出所有Bean的信息
*/
static void showAllBeans(AbstractRefreshableApplicationContext ctx) {
//遍历
for (String name : ctx.getBeanDefinitionNames()) {
System.out.println("name:" + name + ",class:" + ctx.getBean(name).getClass());
}
}
}
beans.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="yjmyzz" />
</beans>
输出: FooA is created! FooA.foo() class yjmyzz.FooA fooA true FooA.destroy() false ------------ FooB is created! FooB.foo() class yjmyzz.FooB fooB true ------------ name:org.springframework.context.annotation.internalConfigurationAnnotationProcessor,class:class org.springframework.context.annotation.ConfigurationClassPostProcessor name:org.springframework.context.annotation.internalAutowiredAnnotationProcessor,class:class org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor name:org.springframework.context.annotation.internalRequiredAnnotationProcessor,class:class org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor name:org.springframework.context.annotation.internalCommonAnnotationProcessor,class:class org.springframework.context.annotation.CommonAnnotationBeanPostProcessor name:org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,class:class org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor name:org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor,class:class org.springframework.context.annotation.ConfigurationClassPostProcessor$EnhancedConfigurationBeanPostProcessor name:fooB,class:class yjmyzz.FooB FooB.destroy()
- 1622: [Usaco2008 Open]Word Power 名字的能量
- 3297: [USACO2011 Open]forgot
- 1740: [Usaco2005 mar]Yogurt factory 奶酪工厂
- 1741: [Usaco2005 nov]Asteroids 穿越小行星群
- 3298: [USACO 2011Open]cow checkers
- 3433: [Usaco2014 Jan]Recording the Moolympics
- 3410: [Usaco2009 Dec]Selfish Grazing 自私的食草者
- 3391: [Usaco2004 Dec]Tree Cutting网络破坏
- 3404: [Usaco2009 Open]Cow Digit Game又见数字游戏
- GIF/PNG/JPG和WEBP/base64/apng图片优点和缺点整理
- 3400: [Usaco2009 Mar]Cow Frisbee Team 奶牛沙盘队
- 3409: [Usaco2009 Oct]Barn Echoes 牛棚回声
- 浅谈webp
- 3385: [Usaco2004 Nov]Lake Counting 数池塘
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 深入探究JVM之垃圾回收算法实现细节
- 深入探究JVM之类加载与双亲委派机制
- 深入探究JVM之方法调用及Lambda表达式实现原理
- synchronized的实现原理——对象头解密
- Golang 汇编入门知识总结
- C语言小笔记(1)
- 这一次搞懂Spring的XML解析原理
- 这一次搞懂Spring自定义标签以及注解解析原理
- 这一次搞懂Spring的Bean实例化原理
- 单片机入门学习十三 STM32单片机学习十 通用定时器
- Spring IOC原理补充(循环依赖、Bean作用域等)
- 这一次搞懂Spring代理创建及AOP链式调用过程
- 这一次搞懂Spring事务注解的解析
- 这一次搞懂Spring事务是如何传播的
- 这一次搞懂SpringMVC原理