복붙노트

[SPRING] Spring에서 인스턴스화 된 빈 목록을 얻으려면 어떻게해야합니까?

SPRING

Spring에서 인스턴스화 된 빈 목록을 얻으려면 어떻게해야합니까?

내 봄 컨텍스트에서 상태가있는 여러 콩을 가지고 있으므로 단위 테스트 전 / 후에 해당 상태를 다시 설정하고 싶습니다.

내 생각은 Spring 컨텍스트의 모든 빈을 그냥 통과하는 헬퍼 클래스에 메서드를 추가하고 @Before 또는 @After로 주석을 붙인 메소드를 확인하고 호출한다.

ApplicationContext에서 인스턴스화 된 Bean의 목록을 얻으려면 어떻게해야합니까?

참고 : 많은 게으른 bean이 있기 때문에 모든 정의 된 bean을 반복하는 솔루션은 쓸모가 없습니다. 일부 테스트에서는 실패하기 때문에 인스턴스화해서는 안됩니다 (즉, java.sql.DataSource가 필요한 bean이 있지만 테스트 콩을 필요로하지 않기 때문에 일한다).

해결법

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

    1.예 :

    예 :

     public static List<Object> getInstantiatedSigletons(ApplicationContext ctx) {
                List<Object> singletons = new ArrayList<Object>();
    
                String[] all = ctx.getBeanDefinitionNames();
    
                ConfigurableListableBeanFactory clbf = ((AbstractApplicationContext) ctx).getBeanFactory();
                for (String name : all) {
                    Object s = clbf.getSingleton(name);
                    if (s != null)
                        singletons.add(s);
                }
    
                return singletons;
    
        }
    
  2. ==============================

    2.나는 그것을 약간 향상시켜야했다.

    나는 그것을 약간 향상시켜야했다.

    @Resource
    AbstractApplicationContext context;
    
    @After
    public void cleanup() {
        resetAllMocks();
    }
    
    private void resetAllMocks() {
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        for (String name : context.getBeanDefinitionNames()) {
            Object bean = beanFactory.getSingleton(name);
            if (Mockito.mockingDetails(bean).isMock()) {
                Mockito.reset(bean);
            }
        }
    }
    
  3. ==============================

    3.이것이 도움이되는지 아닌지 확실하지 않습니다.

    이것이 도움이되는지 아닌지 확실하지 않습니다.

    예를 들어 자신 만의 주석을 만들어야합니다. MyAnnot. 그리고 원하는 클래스에 주석을 추가하십시오. 그리고 다음 코드를 사용하면 인스턴스화 된 bean을 얻을 수 있습니다.

    ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
    scanner.addIncludeFilter(new AnnotationTypeFilter(MyAnnot.class));
    for (BeanDefinition beanDefinition : scanner.findCandidateComponents("com.xxx.yyy")){
        System.out.println(beanDefinition.getBeanClassName());
    }
    

    이렇게하면 맞춤 주석이있는 모든 빈을 얻을 수 있습니다.

  4. ==============================

    4.나는 핵심 ApplicationContextAwareTestBase를 만들었습니다.

    나는 핵심 ApplicationContextAwareTestBase를 만들었습니다.

    이 도우미 클래스는 다음 두 가지 작업을 수행합니다.

    그렇게하면 컨텍스트를 파괴 / 새로 고치지 않고도 싱글 톤 / 모의 상태를 쉽게 재설정 할 수 있습니다.

    예 : 모의 DAO가 있습니다.

    public void MockDao implements IDao {
    
        private Map<Long, Foo> database = Maps.newHashMap();
    
        @Override
        public Foo byId( Long id ) { return database.get( id ) );
    
        @Override
        public void save( Foo foo ) { database.put( foo.getId(), foo ); }
    
        @After
        public void reset() { database.clear(); }
    }
    

    주석은 각 유닛 테스트 후에 내부 상태를 정리하기 위해 reset ()이 호출되는지 확인합니다.

  5. ==============================

    5.이전 답변을 사용하여 Java 8 Streams API를 사용하도록 업데이트했습니다.

    이전 답변을 사용하여 Java 8 Streams API를 사용하도록 업데이트했습니다.

    @Inject
    private ApplicationContext applicationContext;
    
    @Before
    public void resetMocks() {
        ConfigurableListableBeanFactory beanFactory = ((AbstractApplicationContext) applicationContext).getBeanFactory();
        Stream.of(applicationContext.getBeanDefinitionNames())
                .map(n -> beanFactory.getSingleton(n))
                // My ConfigurableListableBeanFactory isn't compiled for 1.8 so can't use method reference. If yours is, you can say
                // .map(ConfigurableListableBeanFactory::getSingleton)
                .filter(b -> Mockito.mockingDetails(b).isMock())
                .forEach(Mockito::reset);
    }
    
  6. from https://stackoverflow.com/questions/14829258/how-can-i-get-a-list-of-instantiated-beans-from-spring by cc-by-sa and MIT license