Spring运行手动注入bean
xiuyuandashen 人气:0有时候,会有这样一个需求,在程序运行时动态生成的对象,需要注入到Spring容器中进行管理。
下面是获取Bean以及注入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 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()); }
附:利用注解向Spring容器中注入Bean
常用注解包含:@Controller、@Service、@Repository、@Component,其中@Controller、@Service、@Repository都是基于@Component的扩展。通常的@Controller用于标识处理前端请求的类,@Service用于标识业务逻辑类,@Repository用于标识DAO层的类,@Component为通用注解,可以标注在任何想要注入容器中的类上面;
@Component //@Controller //@Service //@Repository class Stu{ }
也可以利用@Bean与@Configuration注入,其中@Configuration用于标注一个配置类,@Bean用于标注返回需注入Bean的方法;
@Configuration class MyConfig{ @Bean public Student getStudent(){ return new Student(); } }
总结
加载全部内容