热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Springboot当@Primary遇到循环依赖

今天debug代码时,遇到一个坑publicinterfaceLoopService{voidtestLoop();voidtestInnerLoop();}Se

今天debug代码时,遇到一个坑

public interface LoopService {void testLoop();void testInnerLoop();
}@Service
public class DefaultLoopService implements LoopService {private static final Logger log = LoggerFactory.getLogger(DefaultLoopService.class);@Overridepublic void testLoop() {log.info("DefaultLoopService");}@Overridepublic void testInnerLoop() {log.info("DefaultLoopService--testInnerLoop");}}@Service
@Primary
public class UsingLoopService implements LoopService {private static final Logger log = LoggerFactory.getLogger(UsingLoopService.class);@Autowiredprivate LoopService loopService;@Overridepublic void testLoop() {log.info("UsingLoopService");loopService.testInnerLoop();}@Overridepublic void testInnerLoop() {log.info("UsingLoopService--testInnerLoop");}
}@RestController
public class LoopController {@Autowiredprivate LoopService loopService;@GetMapping("/testLoop")public void testLoop() {loopService.testLoop();}
}

当我请求http://localhost:8080/testLoop时,
期望打印
UsingLoopService : UsingLoopService
UsingLoopService : UsingLoopService–testInnerLoop

但实际却打印
UsingLoopService : UsingLoopService
UsingLoopService : DefaultLoopService–testInnerLoop

我的解决方案

给UsingLoopService命名

@Service("usingLoopService")
@Primary
public class UsingLoopService implements LoopService {private static final Logger log = LoggerFactory.getLogger(UsingLoopService.class);@Autowired@Qualifier("usingLoopService")private LoopService loopService;@Overridepublic void testLoop() {log.info("UsingLoopService");loopService.testInnerLoop();}@Overridepublic void testInnerLoop() {log.info("UsingLoopService--testInnerLoop");}
}

这时打印符合预期
UsingLoopService : UsingLoopService
UsingLoopService : UsingLoopService–testInnerLoop

请教

哪位大神有更好的解决方案,不防写在下面评论区↓\downarrow

后续

今天收到了spring官方的回复

the logic locates in org.springframework.beans.factory.support.DefaultListableBeanFactory@L1533//以下代码摘自spring源码
/*** Find bean instances that match the required type.* Called during autowiring for the specified bean.* &#64;param beanName the name of the bean that is about to be wired* &#64;param requiredType the actual type of bean to look for* (may be an array component type or collection element type)* &#64;param descriptor the descriptor of the dependency to resolve* &#64;return a Map of candidate names and candidate instances that match* the required type (never {&#64;code null})* &#64;throws BeansException in case of errors* &#64;see #autowireByType* &#64;see #autowireConstructor*/protected Map<String, Object> findAutowireCandidates(&#64;Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {String[] candidateNames &#61; BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager());Map<String, Object> result &#61; CollectionUtils.newLinkedHashMap(candidateNames.length);for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {Class<?> autowiringType &#61; classObjectEntry.getKey();if (autowiringType.isAssignableFrom(requiredType)) {Object autowiringValue &#61; classObjectEntry.getValue();autowiringValue &#61; AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);if (requiredType.isInstance(autowiringValue)) {result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);break;}}}for (String candidate : candidateNames) {if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {addCandidateEntry(result, candidate, descriptor, requiredType);}}if (result.isEmpty()) {boolean multiple &#61; indicatesMultipleBeans(requiredType);// Consider fallback matches if the first pass failed to find anything...DependencyDescriptor fallbackDescriptor &#61; descriptor.forFallbackMatch();for (String candidate : candidateNames) {if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {addCandidateEntry(result, candidate, descriptor, requiredType);}}if (result.isEmpty() && !multiple) {// Consider self references as a final pass...// but in the case of a dependency collection, not the very same bean itself.for (String candidate : candidateNames) {if (isSelfReference(beanName, candidate) &&(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&isAutowireCandidate(candidate, fallbackDescriptor)) {addCandidateEntry(result, candidate, descriptor, requiredType);}}}}return result;}


推荐阅读
author-avatar
nana-Wang2602915845
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有