복붙노트

[SPRING] Spring에서 순서대로 콩을 인스턴스화 하시겠습니까?

SPRING

Spring에서 순서대로 콩을 인스턴스화 하시겠습니까?

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

}

콩은 여전히 ​​사전 식 순서로 인스턴스화됩니다.

왜 여기서 작동하지 않습니까?

어쨌든 사전 편찬 명령에 의존 할 수 있습니까?

최신 정보

나는 창조의 질서를 제공 할 수있는 해결책을 원합니다.

목표는 구성 수준에서 정확한 순서로 콜렉션을 채우는 것입니다. 종속 - 작업과 일치하지 않습니다. Spring이 인스턴스화 명령을 내리지 않는 이유에 대한 "설명"도 작업과 일치하지 않습니다.

주문은 주문을 의미합니다 :)

해결법

  1. ==============================

    1.@Order javadoc에서

    @Order javadoc에서

    그래서 스프링을 만들면 콩을 만들 때 @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();
        }
    }
    

    인스턴스화 순서는 변경되지 않지만 순서가 지정된 콜렉션을 가져옵니다.

  2. ==============================

    2.특정 빈이 다른 빈보다 먼저 생성되도록하려면 @DependsOn 주석을 사용할 수 있습니다.

    특정 빈이 다른 빈보다 먼저 생성되도록하려면 @DependsOn 주석을 사용할 수 있습니다.

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

    이것이 주문을 설정하지 않는다는 것을 명심하십시오. 빈 "foo"가 "bar"앞에 만들어지는 것만을 보장합니다. @DependsOn에 대한 JavaDoc

  3. ==============================

    3.MyBean1 및 MyBean2 클래스에서 정적을 제거하면 대부분의 경우 Spring을 사용할 필요가 없을 때 Spring의 기본값이 각 Bean의 단일 인스턴스를 인스턴스화하기 때문에 (예 : Singleton과 유사하게) 순서에 따라 순서를 지정할 수 있습니다. .

    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 a a dependency on bean2
             //forcing it to be created before bean1
             bean2();
    
             return addToAllBeans(new MyBean1());
          }
    
          @Bean
          MyBean2 bean2() {
             //This will cause a a 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<MyBean> allBeans(){
              return new ArrayList<MyBean>();
          }
    
          private <T extends MyBean> T addToAllBeans(T aBean){
              allBeans().add(aBean);
              return aBean;
          }
       }
    
       public static void main(String[] args) {
          new AnnotationConfigApplicationContext(Config.class);
       }
    }
    
  4. from https://stackoverflow.com/questions/36187063/instantiate-beans-in-order-in-spring by cc-by-sa and MIT license