복붙노트

[SPRING] Spring에서 일반적인 인터페이스를 구현하는 모든 bean 가져 오기

SPRING

Spring에서 일반적인 인터페이스를 구현하는 모든 bean 가져 오기

Spring에서 특정 일반 인터페이스 (예 : Filter )를 구현하는 모든 bean에 대한 참조를 얻으려면 어떻게해야합니까?

이것은 최소한의 수의 줄로 달성하고자하는 것입니다.

public interface Filter<T extends Event> {

    boolean approve(T event);

}


public class TestEventFilter implements Filter<TestEvent> {

    public boolean approve(TestEvent event){
        return false;
    }

}

public class EventHandler{
    private ApplicationContext context;

    public void Eventhandler(DomainEvent event) {
        // I want to do something like following, but this is not valid code
        Map<String, Filter> filters = context.getBeansOfType(Filter<event.getClass()>.class);
        for(Filter filter: filters.values()){
            if (!filter.approve(event)) {
                return;  // abort if a filter does not approve the event
            }
        }
        //...
    }

}

현재 구현은 리플렉션을 사용하여 filter.approve가 이벤트를 호출하기 전에이를 수락하는지 확인합니다. 예 :

        Map<String, Filter> filters = context.getBeansOfType(Filter.class);
        for(Filter filter: filters.values()){
            if (doesFilterAcceptEventAsArgument(filter, event)) {
                if (!filter.approve(event)) {
                    return;  // abort if a filter does not approve the event
                }
            }
        }

doesFilterAcceptEventAsArgument가 내가 좋아하는 모든 추악한 작업을 어디에서 벗어나고 싶습니까? 어떤 제안?

해결법

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

    1.당신의 질문이 "Spring이 이것을하기에 더 좋은 방법을 가지고 있는가"면, 대답은 "아니오"입니다. 따라서 메소드는 원시 클래스의 모든 빈을 가져온 다음 반사를 사용하여 제네릭 바인딩을 찾아 대상 클래스와 비교하는 유비쿼터스 방법처럼 보입니다.

    당신의 질문이 "Spring이 이것을하기에 더 좋은 방법을 가지고 있는가"면, 대답은 "아니오"입니다. 따라서 메소드는 원시 클래스의 모든 빈을 가져온 다음 반사를 사용하여 제네릭 바인딩을 찾아 대상 클래스와 비교하는 유비쿼터스 방법처럼 보입니다.

    일반적으로 런타임시 일반 정보를 사용하는 것은 가능한 한 까다로울 수 있습니다. 이 경우 일반 범위를 얻을 수 있지만 수동으로 확인하는 주석 형식으로 사용하는 것 외에는 일반 정의 자체에서 많은 이점을 얻지는 못합니다.

    어쨌든 반환 된 객체에 대해 일종의 검사를 수행해야하므로 원래 코드 블록이 작동하지 않습니다. 유일한 변형은 doesFilterAcceptEventAsArgument 구현에 있습니다. 고전적인 OO 방식은 다음과 같이 두 개의 메소드로 추상 수퍼 클래스를 추가하는 것입니다 (필터 인터페이스에 후자를 추가).

    protected abstract Class<E> getEventClass();
    
    public boolean acceptsEvent(Object event) // or an appropriate class for event
    {
        return getEventClass().isAssignableFrom(event.getClass());
    }
    

    이것은 적절한 클래스 리터럴을 반환하기 위해 모든 구현에서 간단한 getEventClass () 메서드를 구현해야하기 때문에 다소 어려움이 있지만 일반적인 제네릭의 제한 사항입니다. 언어 범위 내에서 이것은 가장 명확한 접근 방법 일 수 있습니다.

    그러나 당신의 가치는 가치가있는 것이 좋습니다.

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

    2.단지 참고할 수있는 가장 간단한 해결책은 다음과 같습니다.

    단지 참고할 수있는 가장 간단한 해결책은 다음과 같습니다.

        Map<String, Filter> filters = context.getBeansOfType(Filter.class);
        for(Filter filter: filters.values()){
            try {
                if (!filter.approve(event)) {
                    return;  // abort if a filter does not approve the event.
                }
            } catch (ClassCastException ignored){ }
        }
    

    그리고 프로토 타이핑을 위해 꽤 잘 작동했습니다.

  3. from https://stackoverflow.com/questions/3228376/get-all-beans-implementing-a-generic-interface-in-spring by cc-by-sa and MIT license