在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 myBeans() { return new ArrayList<>(); } } // PopulateConfig will populate all collections beans @Configuration public static class PopulateConfig implements ApplicationContextAware { @SuppressWarnings("unchecked") @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { Multimap beansMap = MultimapBuilder.hashKeys().arrayListValues().build(); // get all beans applicationContext.getBeansWithAnnotation(CollectionOrder.class) .values().stream() // get CollectionOrder annotation .map(bean -> Pair.of(bean, bean.getClass().getAnnotation(CollectionOrder.class))) // sort by order .sorted((p1, p2) -> p1.getRight().order() - p2.getRight().order()) // add to multimap .forEach(pair -> beansMap.put(pair.getRight().collection(), pair.getLeft())); // and add beans to collections beansMap.asMap().entrySet().forEach(entry -> { Collection collection = applicationContext.getBean(entry.getKey(), Collection.class); collection.addAll(entry.getValue()); // debug System.out.println(entry.getKey() + ":"); collection.stream() .map(bean -> bean.getClass().getSimpleName()) .forEach(System.out::println); }); } } @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) @Documented public @interface CollectionOrder { int order() default 0; String collection(); } } 

它不会更改实例化顺序,但您将获得有序集合。

如果要确保在另一个bean之前创建特定的bean,可以使用@DependsOn批注。

 @Configuration public class Configuration { @Bean public Foo foo() { ... } @Bean @DependsOn("foo") public Bar bar() { ... } } 

请记住,这不会设置顺序,它只保证在“bar”之前创建bean“foo”。 @DependsOn的JavaDoc

您可以通过首先消除类MyBean1MyBean2上的静态来强制在您的示例中进行排序,在几乎每种情况下都不需要使用Spring,因为Spring的默认设置是实例化每个bean的单个实例(类似于Singleton) 。

诀窍是将MyBean1MyBean2声明为@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); } }