在Spring中按顺序实例化bean?
是否可以在Spring中设置实例化顺序?
我不想使用@DependsOn
,我不想使用Ordered
接口。 我只需要一个实例化的命令。
@Order
注释的以下用法不起作用:
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; /** * Order does not work here */ public class OrderingOfInstantiation { public static class MyBean1 {{ System.out.println(getClass().getSimpleName()); }} public static class MyBean2 {{ System.out.println(getClass().getSimpleName()); }} @Configuration public static class Config { @Bean @Order(2) public MyBean1 bean1() { return new MyBean1(); } @Bean @Order(1) public MyBean2 bean2() { return new MyBean2(); } } public static void main(String[] args) { new AnnotationConfigApplicationContext(Config.class); } }
Bean仍按字典顺序实例化。
为什么它在这里不起作用?
我还能依靠词典顺序吗?
UPDATE
我想任何允许提供创建顺序的解决方案。
目标是以正确的顺序在配置级别填充集合。 Depends on
– 与任务不匹配。 关于为什么Spring不喜欢有序实例化的任何“解释” – 也与该任务不匹配。
订单意味着订单:)
来自@Order
javadoc
注意: 仅对特定类型的组件支持基于注释的排序 – 例如,对于基于注释的AspectJ方面。 另一方面,Spring容器中的排序策略通常基于Ordered接口,以便允许以编程方式配置每个实例的顺序。
所以我猜Spring在创建bean时并不遵循@Order()
。
但是如果你只想填充集合,也许这对你来说已经足够了:
import com.google.common.collect.Multimap; import com.google.common.collect.MultimapBuilder; import org.apache.commons.lang3.tuple.Pair; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; import java.lang.annotation.*; import java.util.ArrayList; import java.util.Collection; import java.util.List; @Configuration public class OrderingOfInstantiation { public static void main(String[] args) { new AnnotationConfigApplicationContext(OrderingOfInstantiation.class); } @Component @CollectionOrder(collection = "myBeans", order = 1) public static class MyBean1 {{ System.out.println(getClass().getSimpleName()); }} @Component @CollectionOrder(collection = "myBeans", order = 2) public static class MyBean2 {{ System.out.println(getClass().getSimpleName()); }} @Configuration public static class CollectionsConfig { @Bean List
它不会更改实例化顺序,但您将获得有序集合。
如果要确保在另一个bean之前创建特定的bean,可以使用@DependsOn批注。
@Configuration public class Configuration { @Bean public Foo foo() { ... } @Bean @DependsOn("foo") public Bar bar() { ... } }
请记住,这不会设置顺序,它只保证在“bar”之前创建bean“foo”。 @DependsOn的JavaDoc
您可以通过首先消除类MyBean1
和MyBean2
上的静态来强制在您的示例中进行排序,在几乎每种情况下都不需要使用Spring,因为Spring的默认设置是实例化每个bean的单个实例(类似于Singleton) 。
诀窍是将MyBean1
和MyBean2
声明为@Bean
并强制执行顺序,通过从bean1的初始化方法中调用bean2的bean初始化方法,创建从bean1到bean2的隐式依赖项。
例如:
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; /** * Order does not work here */ public class OrderingOfInstantiation { interface MyBean{ default String printSimpleName(){ System.out.println(getClass().getSimpleName()); } } public class MyBean1 implments MyBean{ public MyBean1(){ pintSimpleName(); } } public class MyBean2 implments MyBean{ public MyBean2(){ pintSimpleName(); } } public class MyBean3 implments MyBean{ public MyBean3(){ pintSimpleName(); } } public class MyBean4 implments MyBean{ public MyBean4(){ pintSimpleName(); } } public class MyBean5 implments MyBean{ public MyBean5(){ pintSimpleName(); } } @Configuration public class Config { @Bean MyBean1 bean1() { //This will cause aa dependency on bean2 //forcing it to be created before bean1 bean2(); return addToAllBeans(new MyBean1()); } @Bean MyBean2 bean2() { //This will cause aa dependency on bean3 //forcing it to be created before bean2 bean3(); //Note: This is added just to explain another point //Calling the bean3() method a second time will not create //Another instance of MyBean3. Spring only creates 1 by default //And will instead look up the existing bean2 and return that. bean3(); return addToAllBeans(new MyBean2()); } @Bean MyBean3 bean3(){ return addToAllBeans(new MyBean3()); } @Bean MyBean4 bean4(){ return addToAllBeans(new MyBean4()); } @Bean MyBean5 bean5(){ return addToAllBeans(new MyBean5()); } /** If you want each bean to add itself to the allBeans list **/ @Bean List allBeans(){ return new ArrayList (); } private T addToAllBeans(T aBean){ allBeans().add(aBean); return aBean; } } public static void main(String[] args) { new AnnotationConfigApplicationContext(Config.class); } }