Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是否可以保证@PostConstruct方法的调用顺序?_Java_Spring_Spring Annotations - Fatal编程技术网

Java 是否可以保证@PostConstruct方法的调用顺序?

Java 是否可以保证@PostConstruct方法的调用顺序?,java,spring,spring-annotations,Java,Spring,Spring Annotations,我有一个使用Spring进行依赖注入的系统。我使用基于注释的自动布线。bean是通过组件扫描发现的,即我的上下文XML包含以下内容: 我在下面创建了一个简单的例子来说明我的问题 有一个Zoo,它是Animal对象的容器。Zoo的开发者在开发Zoo时不知道将包含哪些Animal对象;Spring实例化的一组具体的Animal对象在编译时是已知的,但是有各种构建配置文件导致了不同的Animals集合,并且Zoo的代码在这些情况下不能更改 Zoo的目的是允许系统的其他部分(此处图示为zooponn

我有一个使用Spring进行依赖注入的系统。我使用基于注释的自动布线。bean是通过组件扫描发现的,即我的上下文XML包含以下内容:


我在下面创建了一个简单的例子来说明我的问题

有一个
Zoo
,它是
Animal
对象的容器。
Zoo
的开发者在开发
Zoo
时不知道将包含哪些
Animal
对象;Spring实例化的一组具体的
Animal
对象在编译时是已知的,但是有各种构建配置文件导致了不同的
Animal
s集合,并且
Zoo
的代码在这些情况下不能更改

Zoo
的目的是允许系统的其他部分(此处图示为
zooponner
)在运行时访问
Animal
对象集,而无需明确依赖某些
Animal
对象

实际上,具体的
Animal
类都将由各种Maven工件提供。我希望能够通过简单地依赖包含这些具体的
Animal
s的各种工件来组装我的项目的发行版,并在编译时使所有内容都正确地自动连接

我试图通过让个体
动物依赖
动物园
来解决这个问题(未成功),以便他们可以在
@PostConstruct
期间调用
动物园
上的注册方法。这避免了显式依赖于显式的
动物列表的
Zoo

这种方法的问题在于,
Zoo
的客户只希望在所有
动物
s都注册后才能与之互动。有一组有限的
Animal
s是在编译时已知的,注册都发生在我生命周期的Spring wiring阶段,因此订阅模型应该是不必要的(即,我不希望在运行时将
Animal
s添加到
Zoo

不幸的是,
Zoo
的所有客户都依赖于
Zoo
。这与
动物
动物园
的关系完全相同。因此,
Animal
s和
zooponsor
@PostConstruct
方法以任意顺序调用。下面的示例代码说明了这一点-在
ZooPatron
上调用
@PostConstruct
时,没有
动物
注册,它们都是在几毫秒后注册的

这里有两种类型的依赖关系,我在春季很难表达出来。
Zoo
的客户只想在所有
Animal
s都放进去后使用它。(也许“方舟”会是一个更好的例子……)

我的问题基本上是:解决这个问题的最好方法是什么

@组件
公立动物园{
私有集动物=新HashSet();
公众作废登记册(动物){
动物。添加(动物);
}
公众收集动物(){
归还动物;
}
}
公共抽象类动物{
@自动连线
私人动物园;
@抑制警告(“未使用”)
@施工后
私有void init(){
动物园。登记(本);
}
@组成部分
公共静态类长颈鹿动物{
}
@组成部分
公共静态类猴子扩展动物{
}
@组成部分
公共静态类动物{
}
@组成部分
公共静态类动物{
}
}
公营动物保护人{
公众动物保护人(动物园){
System.out.println(“有”+zoo.getAnimals().size()
+“不同的动物。”);
}
}
@组成部分
公开课考试{
@自动连线
私人动物园;
@抑制警告(“未使用”)
@施工后
私有void init(){
新线程(newrunnable()){
私有静态最终整数迭代=10;
专用静态最终整数延迟=5;
@凌驾
公开募捐{

对于(inti=0;i,IMO,最好的方法是避免在构建对象图的过程中做太多的工作(就像在Java中一样,避免在构造函数中做太多的工作),并且避免在不确定依赖项是否已完全初始化时从依赖项调用方法


如果您只是从
Test#init()中删除@PostConstruct注释
方法,只需从主方法调用它,在创建上下文后,就不会再有此问题了。

我认为,在您的情况下,Zoo对象和所有动物类型之间存在依赖关系。如果您设计Zoo对象以反映此依赖关系,问题就解决了。 例如,您可以执行以下操作:

<bean id="zoo" class="Zoo">
<property name="animals">
<list>
<ref bean="Monkey" />
<ref bean="Tiger" />
<ref bean="Lion" />
</list>
</property>
</bean>


不使用register方法。

我认为没有办法在不引入依赖项的情况下确保@PostConstruct顺序

我想你在尝试混合注射或自我注册时会遇到麻烦。在某种程度上,@PostConstruct call order应该无关紧要——如果它真的重要,那么它可能不是适合这项工作的工具

给你的例子一些想法

  • 试着在动物园动物上安装一个@Autowired:不需要动物自行注册,动物园也知道动物,但不知道动物的情况,这样感觉更干净
  • 保留登记簿,但让外部演员进行登记(有人把动物放在动物园里,对吗?-它们不会独自出现在入口处)
  • 如果您需要随时插入新动物,但不希望手动插入,请在zoo上执行更动态的访问器:不要存储动物列表,而是使用sprin
    <bean id="zoo" class="Zoo">
    <property name="animals">
    <list>
    <ref bean="Monkey" />
    <ref bean="Tiger" />
    <ref bean="Lion" />
    </list>
    </property>
    </bean>
    
    @Component
    public class Zoo {
    
        @Inject
        private Set<Animal> animals = new HashSet<Animal>();
    
        // ...
    }