diff --git a/hutool-extra/src/main/java/cn/hutool/extra/spring/SpringUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/spring/SpringUtil.java index 17d71579a..d6ef9248c 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/spring/SpringUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/spring/SpringUtil.java @@ -4,8 +4,10 @@ import cn.hutool.core.lang.TypeReference; import cn.hutool.core.util.ArrayUtil; import org.springframework.beans.BeansException; import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; @@ -189,6 +191,8 @@ public class SpringUtil implements BeanFactoryPostProcessor, ApplicationContextA * 动态向Spring注册Bean *

* 由{@link org.springframework.beans.factory.BeanFactory} 实现,通过工具开放API + *

+ * 更新: shadow 2021-07-29 17:20:44 增加自动注入,修复注册bean无法反向注入的问题 * * @param Bean类型 * @param beanName 名称 @@ -197,13 +201,52 @@ public class SpringUtil implements BeanFactoryPostProcessor, ApplicationContextA * @since 5.4.2 */ public static void registerBean(String beanName, T bean) { - if(null != beanFactory){ + if (null != beanFactory) { + beanFactory.autowireBean(bean); beanFactory.registerSingleton(beanName, bean); - } else if(applicationContext instanceof ConfigurableApplicationContext){ + } else if (applicationContext instanceof ConfigurableApplicationContext) { ConfigurableApplicationContext context = (ConfigurableApplicationContext) applicationContext; + AutowireCapableBeanFactory factory = context.getAutowireCapableBeanFactory(); + factory.autowireBean(bean); context.getBeanFactory().registerSingleton(beanName, bean); } } + + /** + * 注销bean + *

+ * 将Spring中的bean注销,请谨慎使用 + * + * @param beanName bean名称 + * @author shadow + * @since 5.7.7 + */ + public static void unRegisterBean(String beanName) { + if (applicationContext instanceof ConfigurableApplicationContext) { + ConfigurableApplicationContext context = (ConfigurableApplicationContext) applicationContext; + DefaultSingletonBeanRegistry registry = (DefaultSingletonBeanRegistry) context.getBeanFactory(); + registry.destroySingleton(beanName); + } + } + + /** + * + * 替换Bean + * 组合{@link SpringUtil#unRegisterBean(String)} 和 {@link SpringUtil#replaceBean(String, Object)} + * 将Spring持有bean先注销再注册 + * 需要注意的替换Bean的内部对象的指针指向并不会变化 + * 所有替换的bean被持有的情况下,需要有下至上逐步替换 + * + * @param beanName bean名称 + * @param bean bean + * @param 泛型 + * @author shadow + * @since 5.7.7 + */ + /*public static void replaceBean(String beanName, T bean) { + unRegisterBean(beanName); + registerBean(beanName, bean); + }*/ } diff --git a/hutool-extra/src/test/java/cn/hutool/extra/spring/SpringUtilTest.java b/hutool-extra/src/test/java/cn/hutool/extra/spring/SpringUtilTest.java index ffc4706e7..744aaca93 100644 --- a/hutool-extra/src/test/java/cn/hutool/extra/spring/SpringUtilTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/spring/SpringUtilTest.java @@ -6,10 +6,13 @@ import lombok.Data; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Bean; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import javax.annotation.Resource; import java.util.HashMap; import java.util.Map; @@ -33,6 +36,57 @@ public class SpringUtilTest { Assert.assertEquals("222", registerBean2.getName()); } + /** + * 测试自动注入 + */ + @Test + public void registerBeanTest2() { + TestAutoWired testAutoWired = new TestAutoWired(); + TestBean testBean = new TestBean(); + testBean.setId("123"); + SpringUtil.registerBean("testBean", testBean); + SpringUtil.registerBean("testAutoWired", testAutoWired); + + testAutoWired = SpringUtil.getBean("testAutoWired"); + Assert.assertNotNull(testAutoWired); + Assert.assertNotNull(testAutoWired.getAutowiredBean()); + Assert.assertEquals("123", testAutoWired.getAutowiredBean().getId()); + + } + + /** + * 测试注销bean + */ + @Test + public void unRegisterBeanTest() { + registerBeanTest2(); + Assert.assertNotNull(SpringUtil.getBean("testAutoWired")); + SpringUtil.unRegisterBean("testAutoWired1"); + try { + SpringUtil.getBean("testAutoWired"); + } catch (NoSuchBeanDefinitionException e) { + Assert.assertEquals(e.getClass(), NoSuchBeanDefinitionException.class); + } + } + + /** + * 测试替换bean + + @Test + public void replaceBeanTest() { + registerBeanTest2(); + TestAutoWired testAutoWired = new TestAutoWired(); + TestBean testBean = new TestBean(); + testBean.setId("222"); + Assert.assertEquals("123", SpringUtil.getBean("testBean", TestBean.class).getId()); + SpringUtil.replaceBean("testBean", testBean); + SpringUtil.replaceBean("testAutoWired", testAutoWired); + testAutoWired = SpringUtil.getBean("testAutoWired"); + TestBean testBean1 = testAutoWired.getAutowiredBean(); + Assert.assertEquals("222", testAutoWired.getAutowiredBean().getId()); + Assert.assertEquals("222", testBean1.getId()); + + }*/ @Test public void getBeanTest(){ final Demo2 testDemo = SpringUtil.getBean("testDemo"); @@ -69,4 +123,17 @@ public class SpringUtilTest { return map; } } + + @Data + public static class TestAutoWired { + + @Autowired + // @Resource + private TestBean autowiredBean; + } + + @Data + public static class TestBean { + private String id; + } }