春天自我注射

Pre*_*raj 58 java spring dependency-injection ioc-container

我尝试使用Spring 3.x的以下代码失败了BeanNotFoundException,它应该根据我之前问过的问题的答案 - 我可以使用Spring注入相同的类吗?

@Service
public class UserService implements Service{
    @Autowired
    private Service self;
}
Run Code Online (Sandbox Code Playgroud)

自从我用Java 6尝试这个以来,我发现以下代码工作正常:

@Service(value = "someService")
public class UserService implements Service{
    @Resource(name = "someService")
    private Service self;
}
Run Code Online (Sandbox Code Playgroud)

但我不明白它如何解决循环依赖.

编辑:
这是错误消息.OP在其中一个答案的评论中提到它:

由以下原因引起:org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖项找到类型为[com.spring.service.Service]的匹配bean:期望至少有一个bean可以作为此依赖项的autowire候选者.依赖注释:{@ org.springframework.beans.factory.annotation.Autowired(required = true)}

Sam*_*nen 46

更新:2016年2月

Spring Framework 4.3将正式支持自动装配.可以在此GitHub提交中看到实现.


你不能自己动手的最终原因是Spring的DefaultListableBeanFactory.findAutowireCandidates(String, Class, DependencyDescriptor)方法的实现明确排除了这种可能性.这在以下代码摘录中可见:

for (String candidateName : candidateNames) {
    if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, descriptor)) {
        result.put(candidateName, getBean(candidateName));
    }
}
Run Code Online (Sandbox Code Playgroud)

仅供参考:bean的名称(即,尝试自动装配的bean)是beanName.那个bean实际上是一个autowire候选者,但上面的if-condition返回false(因为candidateName实际上等于beanName).因此,您根本无法自动将bean自动装配(至少不是Spring 3.1 M1).

现在至于这是否是从语义上讲的预期行为,这是另一个问题.;)

我会问Juergen,看看他有什么要说的.

问候,

山姆(核心春天提交者)

ps我打开了一个Spring JIRA问题,考虑使用@Autowired按类型支持自动装配.欢迎观看或投票支持此问题:https://jira.springsource.org/browse/SPR-8450

  • 同意nvrs,同等级的`@Transactional`代理是我在这里的原因.当您拥有成熟的代码库时,"使用AspectJ而不是CGLib"并不是一个有用的答案.使用`@ Resource`可能会解决我的问题,但`@ Autowired`会更好,因为这是我们的标准. (6认同)
  • 我认为这样的事情在某些情况下非常有用,例如,有时你需要让一个方法被事务代理(特别是require_new)包装,这可能是自我调用的.必须"分离"这种功能通常会导致反模式和基因设计不良 (4认同)
  • 记得添加`@Lazy` (3认同)
  • @Amit - 这确实解释了!! 他们只排除了自动连线的候选人,而没有检查@Resource等其他人. (2认同)
  • @Xiangyu,Juergen Hoeller 三天前刚刚记录了这一点:https://github.com/spring-projects/spring-framework/commit/c6752e6023c4948c0f2c007c166ab8ecf677d7b6 (2认同)

sin*_*pop 34

这段代码也适用:

@Service
public class UserService implements Service {

    @Autowired
    private ApplicationContext applicationContext;

    private Service self;

    @PostConstruct
    private void init() {
        self = applicationContext.getBean(UserService.class);
    }
}
Run Code Online (Sandbox Code Playgroud)

我不知道为什么,但似乎Spring可以从ApplicationContextif 创建,但没有初始化.@Autowired在初始化之前工作,它找不到相同的bean.所以,@Resource也许@Autowired之前和之后都有效@PostConstruct.

但我不知道,只是猜测.无论如何,好问题.

  • 很酷,将上下文注入您的应用程序bean.这是有史以来最好的做法! (4认同)
  • @avrilfanomar:好吧,如果一个类需要意识到有自己的代理,那么无论如何你都在破坏DI抽象,所以我认为访问你的容器并没有太糟糕. (4认同)
  • @TTse 将应用程序上下文注入到服务bean中(与spring定制无关)是一种错误的方法。 (2认同)