在Spring中咱们通过getBean来取得对象,但这些对象都是当时定义好的,如果须要操作当时未定义的Bean就须要动静注入、批改和删除Bean
思路
在Spring中,BeanFactory负责管理Bean,具体来说是DefaultListableBeanFactory,咱们只须要获取到以后上下文中的BeanFactory,就能执行其中的注册Bean的办法registerBeanDefinition,注册Bean时须要Bean的信息,Spring提供了BeanDefinitionBuilder.genericBeanDefinition()办法来构建BeanDefinition,用这些办法就能够实现Bean的动静注入
代码实现
测试服务类TestService
创立一个测试类来测试Bean的操作,这个类上没有加注解,Spring在加载时不会主动注入
package com.mantis.bean.service;/** * @Description: * @author: wei.wang * @since: 2020/9/17 12:53 * @history: 1.2020/9/17 created by wei.wang */public class TestService { private String name; private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void print() { System.out.println("获取bean,name=" + name + ",id=" + id); } @Override public String toString() { return "TestService{" + "name='" + name + '\'' + ", id='" + id + '\'' + '}'; }}
SpringContextUtil类
操作Bean的Util类,其中上线文ApplicationContext在SpringBoot启动时设置,也能够间接应用Autowired注入或者依据具体我的项目具体实现
package com.mantis.bean.util;import org.springframework.beans.factory.NoSuchBeanDefinitionException;import org.springframework.context.ApplicationContext;/** * @Description: * @author: wei.wang * @since: 2020/9/17 12:52 * @history: 1.2020/9/17 created by wei.wang */public class SpringContextUtil { private static ApplicationContext applicationContext; //获取上下文 public static ApplicationContext getApplicationContext() { return applicationContext; } //设置上下文 public static void setApplicationContext(ApplicationContext applicationContext) { SpringContextUtil.applicationContext = applicationContext; } //通过名字获取上下文中的bean public static Object getBean(String name) { try { return applicationContext.getBean(name); } catch (NoSuchBeanDefinitionException ex) { return null; } } //通过类型获取上下文中的bean public static Object getBean(Class<?> requiredType) { return applicationContext.getBean(requiredType); }}
启动类SpringBootBeanApplication
在启动类上设置上下文
package com.mantis.bean;import com.mantis.bean.util.SpringContextUtil;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ApplicationContext;@SpringBootApplicationpublic class SpringBootBeanApplication { public static void main(String[] args) { ApplicationContext app = SpringApplication.run(SpringBootBeanApplication.class, args); SpringContextUtil.setApplicationContext(app); }}
注入Bean
向Spring上下文中注入Bean,注入前先查看Bean是否曾经存在
/** * 注册Bean * * @return */ @GetMapping("/bean/register/{beanName}") public String registerBean(@PathVariable String beanName) { //获取context ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) SpringContextUtil.getApplicationContext(); //获取BeanFactory DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory(); //创立bean信息. BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(TestService.class); beanDefinitionBuilder.addPropertyValue("id", "1"); beanDefinitionBuilder.addPropertyValue("name", "张三"); //判断Bean是否曾经注册 Object beanObject = SpringContextUtil.getBean(beanName); if (beanObject != null) { System.out.println(String.format("Bean %s 已注册", beanName)); } else { //动静注册bean. defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition()); //获取动静注册的bean. beanObject = SpringContextUtil.getBean(beanName); if (beanObject != null) { System.out.println(String.format("Bean %s 注册胜利", beanName)); return beanObject.toString(); } else { return "register Bean Error"; } } return "register Bean Success"; }
批改Bean
从SpringContext中获取到指定Bean的Class对象,获取到之后就能够依据字段进行赋值
/** * 动静批改Bean * * @return */ @GetMapping("/bean/update/{beanName}") public String update(@PathVariable String beanName) { ApplicationContext applicationContext = SpringContextUtil.getApplicationContext(); String[] beans = applicationContext.getBeanDefinitionNames(); for (String bean : beans) { // 拿到bean的Class对象 Class<?> beanType = applicationContext.getType(bean); if (beanType == null) { continue; } // 拿到以后bean类型的所有字段 Field[] declaredFields = beanType.getDeclaredFields(); if (beanName.equals(bean)) { for (Field field : declaredFields) { // 从spring容器中拿到这个具体的bean对象 Object beanObject = applicationContext.getBean(bean); // 以后字段设置新的值 try { String fieldName = field.getName(); if ("name".equals(fieldName)) { setFieldData(field, beanObject, "AL113A5"); } else if ("id".equals(fieldName)) { setFieldData(field, beanObject, "12"); } } catch (Exception e) { e.printStackTrace(); } } } } return "update Bean Success"; } private void setFieldData(Field field, Object bean, String data) throws Exception { field.setAccessible(true); Class<?> type = field.getType(); if (type.equals(String.class)) { field.set(bean, data); } else if (type.equals(Integer.class)) { field.set(bean, Integer.valueOf(data)); } else if (type.equals(Long.class)) { field.set(bean, Long.valueOf(data)); } else if (type.equals(Double.class)) { field.set(bean, Double.valueOf(data)); } else if (type.equals(Short.class)) { field.set(bean, Short.valueOf(data)); } else if (type.equals(Byte.class)) { field.set(bean, Byte.valueOf(data)); } else if (type.equals(Boolean.class)) { field.set(bean, Boolean.valueOf(data)); } else if (type.equals(Date.class)) { field.set(bean, new Date(Long.parseLong(data))); } }
移除Bean
将Bean从Spring上下文中移除
/** * 移除Bean * * @return */ @GetMapping("/bean/remove/{beanName}") public String removeBeanDefinition(@PathVariable String beanName) { Object beanObject = SpringContextUtil.getBean(beanName); if (beanObject == null) { System.out.println(String.format("Bean %s 不存在", beanName)); return "remove Error"; } //获取context. ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) SpringContextUtil.getApplicationContext(); //获取BeanFactory DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory(); defaultListableBeanFactory.removeBeanDefinition(beanName); System.out.println(String.format("Bean %s 已移除", beanName)); return "remove Success"; }
测试
写一个操作Bean的办法
/** * 操作Bean * * @return */ @GetMapping("/bean/print/{beanName}") public String print(@PathVariable String beanName) { Object beanObject = SpringContextUtil.getBean(beanName); if (beanObject != null) { ((TestService) beanObject).print(); return beanObject.toString(); } else { System.out.println(String.format("Bean %s 不存在", beanName)); } return String.format("Bean %s 不存在", beanName); }
注册
调用办法
localhost:9000/bean/register/TestService
后果
执行操作Bean的办法,返回后果如下
TestService{name='张三', id='1'}
批改
调用办法
localhost:9000/bean/update/TestService
后果
执行操作Bean的办法,返回后果如下
TestService{name='AL113A5', id='12'}
移除
调用办法
localhost:9000/bean/remove/TestService
后果
执行操作Bean的办法,返回后果如下
Bean TestService 不存在