javaspringdependency-injectionioc-container

Self injection with Spring


I tried the following code with Spring 3.x which failed with BeanNotFoundException and it should according to the answers of a question which I asked before - Can I inject same class using Spring?

@Service
public class UserService implements Service{
    @Autowired
    private Service self;
}

Since I was trying this with Java 6, I found the following code works fine:

@Service(value = "someService")
public class UserService implements Service{
    @Resource(name = "someService")
    private Service self;
}

but I don't understand how it resolves the cyclic dependency.

EDIT:
Here's the error message. The OP mentioned it in a comment on one of the answers:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.spring.service.Service] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}


Solution

  • Update: February 2016

    Self autowiring will be officially supported in Spring Framework 4.3. The implementation can be seen in this GitHub commit.


    The definitive reason that you cannot autowire yourself is that the implementation of Spring's DefaultListableBeanFactory.findAutowireCandidates(String, Class, DependencyDescriptor) method explicitly excludes the possibility. This is visible in the following code excerpt from this method:

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

    FYI: the name of the bean (i.e., the bean that's trying to autowire itself) is beanName. That bean is in fact an autowire candidate, but the above if-condition returns false (since candidateName in fact equals the beanName). Thus you simply cannot autowire a bean with itself (at least not as of Spring 3.1 M1).

    Now as for whether or not this is intended behavior semantically speaking, that's another question. ;)

    I'll ask Juergen and see what he has to say.

    Regards,

    Sam (Core Spring Committer)

    p.s. I've opened a Spring JIRA issue to consider supporting self-autowiring by type using @Autowired. Feel free to watch or vote for this issue here: https://jira.springsource.org/browse/SPR-8450