java - 如何(以及何时)初始化需要访问仅在运行时已知的其他 bean 的 Spring bean?

标签 java spring initialization postconstruct

我有一个在 Java 5 上运行的 Spring Web 应用程序。这个 我的 applicationContext.xml 文件:

<bean id="child1" class="foo.ChildOne" />
<bean id="child2" class="foo.ChildTwo" />
<bean id="main" class="foo.Main">
  <property name="childrenList">
    <list value-type="foo.IChildren">
      <ref bean="child1" />
      <ref bean="child2" />
    </list>
  </property>
</bean>

ChildOneChildTwo 类都实现 IChildren 接口(interface)。在我的 Main 类中,我定义了一个 childrenList,其中填充了 child1child2 bean。 Easy, right?

但将来,可能不会有 child1,相反,我们可能会有一个基于另一个未知类的 child81。而且它仍然需要在不接触当前代码或 XML 文件的情况下工作,只能通过配置来实现。这个 child81 将在其自己的 applicationContext 文件(在 JAR 中)中定义,我们将在数据库字段中列出 bean 名称(child2、child81 等)。

我想这不是一个好的设计模式;最有可能的是,这是一个可怕的、可怕的、痛苦的、你最好趁还能跑的设计,这将在未来的几年里困扰着我。但我没有定义它,并且我无法更改它,所以请假设对于这个问题来说这是可以的。

我必须在运行时以某种方式检索它们,而不是使用 applicationContext.xml 自己注入(inject) bean。我也无法使用 Autowiring ,因为我不知道这些 bean 是什么类,我只知道它们的所有类都实现了 IChildren

所以我创建了我的主 bean 类 ApplicationContextAware 并添加了此方法:

public void loadChildren() {
  if (childrenList == null) {
    childrenList = new LinkedList<IChildren>();
    for (String name : theListOfBeanNames) {
      childrenList.add((IChildren) context.getBean(name));
    }
  }
}

一切正常;每个 bean 都在其自己的 applicationContext 中定义,然后我按名称检索它们。但是......我什么时候调用loadChildren()?到目前为止,我正在每个方法的第一行中执行此操作。由于存在空检查,因此它只会初始化列表一次。但肯定有一种更简单/更干净/更好的方法来做到这一点?

我认为我不能在 applicationContext 中使用 init-method="loadChildren" 属性,因为如果我的主 bean 正在运行,它就会失败在所有 child 之前加载...并且我无法控制加载顺序。或者我可以吗?

这是来 self 的 web.xml 文件:

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
    /WEB-INF/application-context/applicationContext-*.xml
    ,classpath*:WEB-INF/application-context/applicationContext-children.xml
  </param-value>
</context-param>

(我们使用“classpath* notation ”从 JAR 中加载每个 applicationContext-children.xml 文件)。如果我颠倒顺序并将子 XML 放在主要 XML 之前,是否可以确保它们按照特定顺序加载?不管我们使用什么版本的应用服务器?

我还看到了@PostConstruct annotation如果我可以将其添加到我的 loadChildren 方法中,这将很有用。但什么时候会被调用呢?我读到这是在注入(inject)完成之后,但是......仅适用于当前的 bean,对吧?它不能确保所有其他 bean 都已加载?

还有其他选择吗?

最佳答案

Spring 可以为你做到这一点:

@Component
public class MyComponent {
    @Autowired
    private final List<IChildren> children;

    ...
}

除了实现 IChildren 之外,这将 Autowiring 所有内容。

关于java - 如何(以及何时)初始化需要访问仅在运行时已知的其他 bean 的 Spring bean?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48149618/

相关文章:

java - 如何强制 HtmlUnit 在 GWT 测试用例中解析 UTF-8 中的 Javascript 文件?

java - 从 ViewPager Fragment 监听 DialogFragment dismiss 事件

Spring-boot 和 Spring-Kafka 兼容性矩阵

spring - 覆盖 bean 定义不能按预期工作

java - 如何在启动/初始化时更改/编辑 JPanel 对象

python - 从可能丢失的 dict 值初始化 Python 变量

java - JOOQ别名构造

java - 使用 Java/sql 存储和检索数据时遇到问题

java - 如何仅更新 Spring JPA 存储库中所有字段的子集?

java - 始终通过上下文在 Spring 服务中注入(inject)一些字段