java - 在Spring中按顺序实例化bean?

标签 java spring annotations

是否可以在 Spring 中设置实例化顺序?

我不想使用@DependsOn 也不想使用Ordered 接口(interface)。我只需要一个实例化顺序。

@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 仍然按字典顺序实例化。

为什么它在这里不起作用?

我可以依赖字典顺序吗?

更新

我想要任何允许提供创建顺序的解决方案。

目标是以正确的顺序在配置级别填充集合。 Depends on -- 不匹配任务。关于为什么 Spring 不喜欢有序实例化的任何“解释”——也不符合任务。

订单就是订单:)

最佳答案

来自 @Order javadoc

NOTE: Annotation-based ordering is supported for specific kinds of components only — for example, for annotation-based AspectJ aspects. Ordering strategies within the Spring container, on the other hand, are typically based on the Ordered interface in order to allow for programmatically configurable ordering of each instance.

所以我猜想 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<Object> 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<String, Object> 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();
    }
}

它不会改变实例化顺序,但你会得到有序的集合。

关于java - 在Spring中按顺序实例化bean?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36187063/

相关文章:

java - Spring JPA 数据存储库没有发挥应有的作用

ios - 构建 MapView 注释非常慢

java - 从 Java 5 开始不再需要 serialVersionUID?

java - 其余模板的 Spring JsonProcessingExceptin NoClassDefFoundError

hibernate - 如何在基于 Wicket、Spring、Hibernate 的 Web 应用程序中正确使用 LoadableDetachableModel?

annotations - AspectJ - 检索带注释的参数列表

Java 注解处理 Messager API 消息未显示

java - 印度语言的拼音搜索

java - 使用 Google Drive API 从 Google Drive 直接下载

java - Mac 从 Java 程序中弹出 USB 磁盘