当前位置: 首页 > 面试题库 >

在春天按顺序实例化bean?

经国安
2023-03-14
问题内容

是否可以在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仍按字典顺序实例化。

为什么在这里不起作用?

无论如何,我可以依靠词典顺序吗?

更新

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

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

订单表示订单:)


问题答案:

@Orderjavadoc

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

因此我猜想Spring @Order()在创建bean时不会遵循。

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

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

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



 类似资料:
  • 问题内容: 我试图将JVM中的初始化和实例化过程组合在一起,但是JLS在一些细节上有点笨拙,因此,如果有人介意清理一些细节,将不胜感激。到目前为止,这是我能够弄清楚的。 初始化 递归初始化该类及其接口的静态最终变量,这些变量是编译时间常数。 从递归中退出,按文本顺序处理静态块和静态字段。 实例化 递归初始化作为编译时间常数的类的最终实例变量。 按文本顺序退出递归处理非静态块和实例字段,并在返回时将

  • 问题内容: 直观上似乎很清楚,在Java中,实例变量初始化器是按照它们在类声明中出现的顺序执行的。 在我正在使用的JDK中,似乎确实是这种情况。例如,以下内容: 打印(换句话说,y选择的默认值z)。 实际可以保证此顺序吗?我一直在浏览JLS,找不到任何明确的确认。 问题答案: 是的。 se7 JLS在12.5执行部分中介绍了实例变量的初始化顺序: … 4.执行此类的实例初始值设定项和实例变量初始值

  • 问题内容: 我正在从头开始一个新的Java Web应用程序。 我对Spring Framework经验不足,但是我知道我想使用其某些功能,例如Transaccions Management。 另一方面,我真的很喜欢Guice进行依赖注入。 我知道Guice和Spring可以一起工作:http : //www.jroller.com/mindcrime/entry/an_example_of_int

  • 问题内容: 我在mysql排序中寻找一些调整,我通常从表中选择记录,然后按Name(varchar)ASC排序记录, 但编号始终是第一位的 这是我的问题的一些示例( 注意。mysql首先用0-9排序记录 ) 我想要的是字母顺序,然后是数字 所需的输出 问题答案: 使用以下子句:

  • JAR2(非Spring项目)

  • 问题内容: 如果我有这样的数据: 我如何将命令连接成这样: 我在下面使用了此查询,但命令列的顺序不依其顺序号而定: 任何意见和建议将不胜感激。^ _ ^ 问题答案: 永远不要使用。阅读为什么不在Oracle中使用WM_CONCAT函数? 请参阅本主题https://stackoverflow.com/a/28758117/3989608。 它没有记录,并且依赖的任何应用程序一旦升级到后都将无法工作