在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 不存在