• 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>
    View Code

    输出:
    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()

  • 相关阅读:
    《Spring2之站立会议1》
    《Spring1之第十次站立会议》
    《Spring1之第九次站立会议》
    《Spring1之第八次站立会议》
    《Spring1之第七次站立会议》
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/how-to-dynamic-destroy-or-register-bean-to-spring-container.html
Copyright © 2020-2023  润新知