Spring expected at least 1 bean which qualifies as autowire candidate for this dependency

Tobia picture Tobia · Jul 4, 2012 · Viewed 113.5k times · Source

I have a trouble with this Autowire:

@Controller
public class ChiusuraController {

    @Autowired
    private ChiusuraProvider chiusuraProvider;
}

with this bean:

@Service @Transactional
public class ChiusuraProvider extends ThreadProvider {


    public void run() {}
}

that extends

public abstract class ThreadProvider extends Thread implements InitializingBean, Runnable, DisposableBean {
...
}

I get this error:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'chiusuraController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.cinebot.service.ChiusuraProvider com.cinebot.web.controller.ChiusuraController.chiusuraProvider; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.cinebot.service.ChiusuraProvider] 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)}

I saw that I did not get this error if I remove extends ThreadProvider of autowired class, but I really need ThreadProvider abstract class.

Answer

Biju Kunjummen picture Biju Kunjummen · Jul 4, 2012

If there is an interface anywhere in the ThreadProvider hierarchy try putting the name of the Interface as the type of your service provider, eg. if you have say this structure:

public class ThreadProvider implements CustomInterface{
...
}

Then in your controller try this:

@Controller
public class ChiusuraController {

    @Autowired
    private CustomInterface chiusuraProvider;
}

The reason why this is happening is, in your first case when you DID NOT have ChiusuraProvider extend ThreadProvider Spring probably was underlying creating a CGLIB based proxy for you(to handle the @Transaction).

When you DID extend from ThreadProvider assuming that ThreadProvider extends some interface, Spring in that case creates a Java Dynamic Proxy based Proxy, which would appear to be an implementation of that interface instead of being of ChisuraProvider type.

If you absolutely need to use ChisuraProvider you can try AspectJ as an alternative or force CGLIB based proxy in the case with ThreadProvider also this way:

<aop:aspectj-autoproxy proxy-target-class="true"/>

Here is some more reference on this from the Spring Reference site: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/classic-aop-spring.html#classic-aop-pfb