programing

spring @AutoWired Map을 사용할 수 있습니까?

newsource 2023. 8. 18. 22:41

spring @AutoWired Map을 사용할 수 있습니까?

지도 여기 있습니다.

@Autowired
private Map<String, ISendableConverter> converters;

그리고.ISendableConverter

public interface ISendableConverter {

    ISendableMsg convert(BaseMessage baseMessage);

    String getType();
}

구현하는 클래스가 몇 개 있습니다.ISendableConverter

변수에 주입하고 싶습니다.converters용수철을 이용하여@Autowried주석

값으로서의 클래스의 인스턴스 및 방법의 결과getType()열쇠로

이것처럼 말이다.

@Component
public class SendableVoiceMsgConverter implements ISendableConverter {

    @Override
    public ISendableMsg convert(BaseMessage baseMessage) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String getType() {
        return "VOICE";
    }
}

이것이 가능합니까?그리고 어떻게?

Spring Java 구성을 사용하여 원하는 키로 자동으로 초기화된 맵을 만들 수 있습니다.

수업 시간에 주석이 달린 것으로 주석을 달았습니다.@Configuration주석:

@Autowired
private List<ISendableConverter> sendableConverters;

@Bean
public Map<String, ISendableConverter> sendableConvertersMap() {
    Map<String, ISendableConverter> sendableConvertersMap = new HashMap<>();
    for (ISendableConverter converter : sendableConverters) {
        sendableConvertersMap.put(converter.getType(), converter);
    }
    return sendableConvertersMap;
}

이 맵에 다음을 삽입할 때보다:

@Resource()
private Map<String, ISendableConverter> sendableConverters;

선택적으로 일부 선택기 문자열을 에 추가할 수 있습니다.@Resource같은 유형의 맵을 더 정의한 경우 주석을 입력합니다.

이런 식으로 구현하기만 하면 됩니다.ISendableConverter당신의 스프링 빈에 의해 그리고 그것은 위에 정의된 지도에 자동으로 나타날 것입니다.각 구현에 대해 지도 항목을 수동으로 생성할 필요가 없습니다.

@Resource - 이 코드를 테스트하지 않았습니다.

@Resource(name="converters")
private Map<String, ISendableConverter> converters;

또는

@Value("#{converters}")
private Map<String, ISendableConverter> converters;

Spring 문서에서

(...) 컬렉션 또는 지도 유형으로 정의된 콩은 유형 일치가 적절하게 적용되지 않기 때문에 @Autowired를 통해 주입할 수 없습니다.이러한 콩에 대해 @Resource를 사용합니다. 특정 컬렉션을 참조하거나 고유한 이름으로 콩을 매핑합니다.

이것은 당신이 준비하는 경우에만 효과가 있을 것입니다.converters이런 콩:

<util:map id="converters" scope="prototype" map-class="java.util.HashMap" 
          key-type="java.lang.String" value-type="...ISendableConverter">
    <entry key="VOICE" value="sendableVoiceMsgConverter" />
</util:map>

이것도 비슷한 질문입니다.

다음과 같은 작업을 수행할 수 있습니다.

@SuppressWarnings("unused")
private List<OneTypeImageLoader> imageLoaders;
private Map<String, OneTypeImageLoader> imageLoaderMap=new HashMap<>();

@Autowired
public void setImageLoaders(List<OneTypeImageLoader> imageLoaders) {
    this.imageLoaders = imageLoaders;
    imageLoaders.forEach(l-> {
        imageLoaderMap.put(l.getType(), l);
    });
}

이런 것을 시도해 보세요, 저에게 효과가 있습니다.

private Map<String, ISendableConverter> converters;

@Autowired
public void setUploadServices(Set<ISendableConverter> converters){
    this.conveters = converters.stream()
        .collect(Collectors.toMap(ISendableConverter::getType, Function.identity()));
}

생성자 주입을 사용해도 동일한 결과를 얻을 수 있습니다.

private Map<String, ISendableConverter> converters;

@Autowired
public Foo(Set<ISendableConverter> converters) {
    this.conveters = converters.stream()
        .collect(Collectors.toMap(ISendableConverter::getType, Function.identity()));
}
@Component("VOICE")
public class SendableVoiceMsgConverter implements ISendableConverter {

    @Override
    public ISendableMsg convert(BaseMessage baseMessage) {
        // TODO Auto-generated method stub
        return null;
    }
}

형식 이름을 구성 요소 주석에 직접 추가하면 됩니다.

먼저 빈 이름을 반환 값과 같이 설정합니다.getType()

@Component("VOICE")
public class SendableVoiceMsgConverter implements ISendableConverter {

    @Override
    public ISendableMsg convert(BaseMessage baseMessage) {
        // TODO Auto-generated method stub
        return null;
    }
}

다음과 같이 사용할 수 있습니다.

@Autowired
private Map<String, ISendableConverter> converters;

이 지도의 V형은 빈의 인스턴스이고, K형은 빈의 이름입니다.

이는 다음을 통해 달성할 수 있습니다.spring-componentmap(https://github.com/krud-dev/spring-componentmap)

예를 들어 다음을 수행합니다.

public interface ISendableConverter {

    ISendableMsg convert(BaseMessage baseMessage);

    @ComponentMapKey
    String getType();
}

@Component
public class SendableVoiceMsgConverter implements ISendableConverter {

    @Override
    public ISendableMsg convert(BaseMessage baseMessage) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String getType() {
        return "VOICE";
    }
}

// Call the converter by type
@Component
class SendableMsgConverter {

    // @ComponentMap replaces @Autowired in this case
    @ComponentMap
    private Map<String, ISendableConverter> converterMap;

    public ISendableMsg convert(BaseMessage baseMessage) {
        ISendableConverter converter = converterMap.get(baseMessage.getType());
        return converter.convert(baseMessage);
    }
}

고지 사항:공동 개발했습니다.spring-componentmap

더 일반적으로 만들고 다음과 같은 것을 만들 수 있습니다.

    public interface BasicStrategy {
        String getKey();
    }

    public final class StrategyMap<K extends BasicStrategy> extends HashMap<String, K> {

    public StrategyMap(List<K> strategies) {
        super(strategies.stream().collect(Collectors.toMap(K::getKey, Function.identity())));
    }

    @Override
    public K get(Object key) {
        BasicStrategy basicStrategy = super.get(key);
        if (basicStrategy == null) {
            throw new RuntimeException("No strategy found for key: '" + key + "'");
        }
        return (K) basicStrategy;
    }
}

이제 이것을 사용할 수 있습니다.StrategyMap다음과 같이 코드 주위의 모든 곳에서:

private StrategyMap<ISendableConverter> converters;

@Autowired
public Foo(List<ISendableConverter> converters) {
    this.conveters = new StrategyMap<>(converters);
}

이 접근 방식은 다음을 생성합니다.StrategyMap또한 값을 찾을 수 없는 경우의 논리를 중앙 집중화할 수 있습니다.

PS: 물론입니다.ISendableConverter확장해야 합니다.BasicStrategyinterface 이름

언급URL : https://stackoverflow.com/questions/20918825/can-spring-autowired-map