zoukankan      html  css  js  c++  java
  • SPRING 动态注册BEAN

    场景

    有些情况下,不能直接使用BEAN的方式:

    @Bean(name = "storage")
        public DataSourceProxy storageDataSourceProxy(@Qualifier("originStorage") DataSource dataSource) {
            return new DataSourceProxy(dataSource);
        }

    比如有些情况下,需要将BEAN 动态加入SPRING 容器中,但是上面的方式是固定的,实现不了在容器中动态注册BEAN。

    实现方式

    增加一个动态注册工具类:

    package com.redxun.common.utils;
    
    import org.springframework.beans.factory.config.BeanDefinition;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.ConfigurableApplicationContext;
    
    public class ManualRegistBeanUtil {
    
        /**
         * 主动向Spring容器中注册bean
         *
         * @param applicationContext Spring容器
         * @param name               BeanName
         * @param clazz              注册的bean的类性
         * @param args               构造方法的必要参数,顺序和类型要求和clazz中定义的一致
         * @param <T>
         * @return 返回注册到容器中的bean对象
         */
        public static <T> T registerBean(ConfigurableApplicationContext applicationContext, String name, Class<T> clazz,
                                         Object... args) {
            if(applicationContext.containsBean(name)) {
                Object bean = applicationContext.getBean(name);
                if (bean.getClass().isAssignableFrom(clazz)) {
                    return (T) bean;
                } else {
                    throw new RuntimeException("BeanName 重复 " + name);
                }
            }
            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
            for (Object arg : args) {
                beanDefinitionBuilder.addConstructorArgValue(arg);
            }
            BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
            BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry) applicationContext.getBeanFactory();
            beanFactory.registerBeanDefinition(name, beanDefinition);
            return applicationContext.getBean(name, clazz);
        }
    
    }
    applicationContext:spring 容器上下文

    name:bean 的名称
    clazz:需要注入的类
    args : 类的构造参数。

    注入无依赖的Bean

     编写代码:

    import lombok.extern.slf4j.Slf4j;
    
    import java.util.Random;
    
    @Slf4j
    public class ManualBean {
    
        private int id;
        private String name;
    
        public ManualBean() {
            Random random = new Random();
            id = random.nextInt(100);
        }
    
        public ManualBean(String msg) {
             this.name=msg;
        }
    
        public String print( ) {
            return "[ManualBean] print : " + name + " id: " + id;
        }
    }

    注入测试:

    import com.redxun.common.utils.ManualRegistBeanUtil;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.stereotype.Component;
    
    @Component
    public class BeanRegisterAutoConf {
    
        public BeanRegisterAutoConf(ApplicationContext applicationContext) {
            System.out.println("BeanRegisterAutoConf init: " + System.currentTimeMillis());
            registerManualBean((ConfigurableApplicationContext) applicationContext);
        }
    
    
        private void registerManualBean(ConfigurableApplicationContext applicationContext) {
            // 主动注册一个没什么依赖的Bean
            ManualBean manualBean = ManualRegistBeanUtil.registerBean(applicationContext, "manualBean", ManualBean.class,"RAY");
            manualBean.print();
    
        }
    
    
    }

    这里使用了构造参数的方式进行注入。

    测试注入是否可用

    编写测试用例

    @Test
        public void testRegseterBean(){
            ManualBean bean= SpringUtil.getBean("manualBean");
            String str= bean.print();
            System.err.println(str);
        }

    注入有依赖的BEAN

    import org.springframework.beans.factory.annotation.Autowired;
    
    import java.util.Random;
    
    public class ManualDIBean {
    
        private int id;
    
        @Autowired
        private OriginBean originBean;
    
        private String name;
    
        public ManualDIBean(String name) {
            Random random = new Random();
            this.id = random.nextInt(100);
            this.name = name;
        }
    
        public String print(String msg) {
            String o = originBean.print(" call by ManualDIBean! ");
            return "[ManualDIBean] print: " + msg + " id: " + id + " name: " + name + " originBean print:" + o;
        }
    }

    这里注入了OriginBean bean。

    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    
    import java.time.LocalDateTime;
    
    @Slf4j
    @Component
    public class OriginBean {
    
        private LocalDateTime time;
    
        public OriginBean() {
            time = LocalDateTime.now();
        }
    
        public String print(String msg) {
            return "[OriginBean] print msg: " + msg + ", time: " + time;
        }
    }

    测试注册BEAN

    @Component
    public class BeanRegisterAutoConf {
    
        public BeanRegisterAutoConf(ApplicationContext applicationContext) {
            System.out.println("BeanRegisterAutoConf init: " + System.currentTimeMillis());
            registerManualBean((ConfigurableApplicationContext) applicationContext);
        }
    
    
        private void registerManualBean(ConfigurableApplicationContext applicationContext) {
            // manualDIBean 内部,依赖由Spring容器创建的OriginBean
            ManualDIBean manualDIBean = ManualRegistBeanUtil.registerBean(applicationContext, "manualDIBean",
                    ManualDIBean.class, "依赖OriginBean的自定义Bean");
            manualDIBean.print("test print manualDIBean");
        }
    }

    编写单元测试从容器中获取bean。

    @Test
    public void testRegseterBean(){
    ManualDIBean bean= SpringUtil.getBean("manualDIBean");
    String str= bean.print("Hello");
    System.err.println(str);
    }
     
  • 相关阅读:
    Using AlloyTouch to control three.js 3D model
    AlloyTouch与three.js 3D模型交互
    移动Web触摸与运动解决方案AlloyTouch开源啦
    transformjs玩转星球
    swing with transformjs
    和transformjs一起摇摆
    getting started with transformjs
    移动Web利器transformjs入门
    腾讯AlloyTeam移动Web裁剪组件AlloyCrop正式开源
    Why AlloyFinger is so much smaller than hammerjs?
  • 原文地址:https://www.cnblogs.com/yg_zhang/p/13032797.html
Copyright © 2011-2022 走看看