在Spring中按顺序实例化bean? [英] Instantiate beans in order in Spring?

查看:29
本文介绍了在Spring中按顺序实例化bean?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is it possible to set order of instantiation in Spring?

我不想使用 @DependsOn 并且我不想使用 Ordered 接口.我只需要一个实例化顺序.

I don't want to use @DependsOn and I don't want to use Ordered interface. I just need an order of instantiation.

@Order 注释的以下用法不起作用:

The following usage of @Order annotation does not work:

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

Beans are still instantiated in lexicographic order.

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

Why it does not work here?

我可以依赖字典顺序吗?

Can I rely of lexicographic order anyway?

更新

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

I would like any solution allowing to provide order of creation.

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

The goal is to populate collections at config level in correct order. Depends on -- does not match the task. Any "explanations" on why Spring does not like to have ordered instantiations -- also does not match the task.

订单意味着订单:)

推荐答案

From @Order javadoc

From @Order javadoc

注意:支持基于注解的排序仅针对特定类型的组件——例如,基于注解的 AspectJ 方面.另一方面,Spring 容器内的排序策略通常基于 Ordered 接口,以便允许以编程方式配置每个实例的排序.

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().

So I guess Spring just doesn't follow @Order() when creating beans.

但如果您只想填充集合,也许这对您来说已经足够了:

But if you just want to populate collections, maybe this is good enough for you:

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();
    }
}

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

It won't change instantiation order, but you'll get ordered collections.

这篇关于在Spring中按顺序实例化bean?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆