【问题标题】:Adding dynamic beans to spring web context将动态 bean 添加到 Spring Web 上下文
【发布时间】:2012-09-06 05:45:20
【问题描述】:

我需要能够将新的 bean 添加到 Spring Web 上下文(在任何范围内),以便在编译时在类路径中定义和可能未定义的类。

例如,我可以动态创建一些此类,然后为此类注册一个单例或会话 bean。

我阅读了一些有关 BeanFactoryPostProcessor 的信息,但不确定它是否可以在 Web 上下文中工作,如果我理解正确,它只会在实际加载 bean 实例之前工作,而不是之后,还是我错了?

我无法在 AnnotationConfigWebApplicationContext 中找到有关如何执行此操作的信息,并且至少在我的测试中,我动态创建的所有 bean 都没有注入到其他实例中,即使它们是我也只看到了方法注册 Singleton bean 但不注册其他范围:

ctx.getBeanFactory().registerSingleton("dummy", dummy);

警察局

我发现了这个问题:Dynamic creation of beans in Spring 但是当我尝试像这样将任何 bean、bean 定义或 bean 定义构建器添加到 web 上下文时,bean 不会被加载:

AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.setServletContext(servletContext);
ctx.refresh();
//
log.trace("Registering first test bean");
Test test = new Test();
test.setDummy("x1");
ctx.getBeanFactory().registerSingleton("myTestBean1", test);        

log.trace("Registering second test bean");
BeanDefinition testDef = new RootBeanDefinition(Test.class);        
testDef.setScope(BeanDefinition.SCOPE_SINGLETON);        
ctx.getBeanFactory().registerSingleton("myTestBean2", testDef);

Test dummy1 = (Test)ctx.getBean("myTestBean1");
Object dummy2 = ctx.getBean("myTestBean2");

log.trace("beans: 1: {}; 2: {}", dummy1, dummy2); //<--this works, but...
ctx.refresh();

ctx.register(MyConfig.class); //configuring other beans

...当我从另一个在 MyConfig.class 中配置或使用 @Component 注释的 bean 执行此操作时(它甚至可能是另一个动态组件):

@Autowire Test myTestBean1;
//Or this:
Object a = this.ctx.getBean("myTestBean1"); //Or myTestBean2

它抛出一个 NoSuchBeanDefinitionException

请帮帮我!!我环顾四周并没有找到任何有用的信息,或者也许我有,但我无法在这么短的时间内测试我在网络上找到的所有内容,而且 spring 文档似乎只适用于正常情况和 xml 配置,而不是对于我正在尝试做的这些疯狂的事情,而不是用于编程配置。

【问题讨论】:

  • 我想知道在 Java 代码中显式处理对象生命周期是否不会让事情变得更简单

标签: java spring


【解决方案1】:

您所追求的无法完成,抱歉。最初创建 bean 时会发生自动装配。在您的情况下,您希望在将 bean 添加到工厂之前连接一个 bean,这当然行不通 - Spring 不会进行时间旅行。

我认为你追求的是工厂模式。在 Spring 中,您可以通过实现 FactoryBean 将 bean 的实例化推迟到您创建的工厂。在这里阅读更多:

【讨论】:

  • 谢谢,但在示例中,我在将 bean 自动装配到另一个 bean 之前创建了 bean,我将问题编辑得更清楚,但看起来很有趣......如果我需要,我会看看这个另一种方法
  • @Lando 在您的示例中,您首先在第二行调用 ctx.refresh(),它构建了整个 bean 工厂并处理所有自动装配。这发生在你做任何其他事情之前。无论如何,在运行时手动插入 bean 并不是 Spring 的工作方式。我相信你可以让它以某种方式运行,但它不会很漂亮。如果您需要延迟/推迟 bean 创建,您应该使用范围和/或工厂和接口。
  • 如果我之前不调用刷新,我得到一个 IllegalStateException,我检查代码并验证工厂在注册新单例时不为空。工厂的问题是我仍然需要定义 bean 的名称,以便 spring 将创建委托给工厂。我的想法不多了:(
  • @Lando 不要针对框架工作,使用它。您正在尝试做一些与 Spring 的意图和设计相反的事情。花点时间想想你的每个对象的生命周期以及你想要做什么,你会发现你没有想法的原因是因为你的基本假设是倒退的。
  • 正确的博文链接似乎是spring.io/blog/2011/08/09/what-s-a-factorybean
猜你喜欢
  • 2011-05-31
  • 1970-01-01
  • 2013-04-12
  • 2020-04-05
  • 2017-08-18
  • 2011-04-07
  • 2015-01-31
  • 1970-01-01
相关资源
最近更新 更多