Manually inject beans at Spring runtime

Sometimes, there is such a requirement that objects dynamically generated when the program is running need to be injected into the Spring container for management.

The following is the tool class for getting Bean and injecting Bean

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Map;

@Component
public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtils.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static Object getBean(String name) throws BeansException {
        return applicationContext.getBean(name);
    }

    public static Object getBean(Class name) throws BeansException {
        return applicationContext.getBean(name);
    }

    /**
     * bean注入spring容器
     * map[id,className,...]
     * id 为 bean的标识
     * className 为 类的全限定类名
     * ... 为其他属性
     * @param map
     */
    public static void injectBean(Map<String, String> map) {
        String className = map.get("className");
        Class<?> aClass;
        if (className == null) {
            throw new RuntimeException("map参数缺少className");
        }

        try {
            aClass = Class.forName(className);
            if (aClass == null) {
                throw new RuntimeException("className不存在");
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(aClass);
        Field[] declaredFields = aClass.getDeclaredFields();
        for (int i = 0; i < declaredFields.length; i++) {
            String fieldName = declaredFields[i].getName();
            if (map.get(fieldName) != null) {
                // 必须设置可访问,否则下面的操作做不了
                // declaredFields[i].setAccessible(true);
                builder.addPropertyValue(fieldName, map.get(fieldName));
            }
        }
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) applicationContext;
        // 注册bean 第一个参数为 name ,第二个为 bean定义类
        String id = map.get("id");
        if (id == null) {
            registry.registerBeanDefinition(className, builder.getBeanDefinition());
            return;
        }
        registry.registerBeanDefinition(id, builder.getBeanDefinition());
    }

}
复制代码

test

@Test
   public void test2() {
      HashMap<String, String> map = new HashMap<>();
      map.put("id", "helloTask");
      map.put("className", "com.example.demo.Task.HelloTask4");
      // 注册bean
      SpringUtils.injectBean(map);
//    HelloTask4 helloTask =(HelloTask4) SpringUtils.getBean(HelloTask4.class);
      HelloTask4 helloTask = (HelloTask4) SpringUtils.getBean("helloTask");
      System.out.println(helloTask.getClass());
   }
复制代码

image.png

Guess you like

Origin juejin.im/post/7103444236682395655
Recommended