SPRING 动态注册BEAN

Posted 自由港

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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);
    }

注入有有依赖

 

 

 

以上是关于SPRING 动态注册BEAN的主要内容,如果未能解决你的问题,请参考以下文章

SPRING 动态注册BEAN

Spring运行时动态注册bean

Spring - BeanDefinitionRegistryPostProcessor 扩展接口 动态注册bean

Spring - BeanDefinitionRegistryPostProcessor 扩展接口 动态注册bean

Spring BootSpring Boot之使用ImportBeanDefinitionRegistrar类实现动态注册Bean

SpringBoot运行时动态注册Bean到IOC容器中