简体   繁体   中英

Spring 3.2: Cannot autowire @Service annotated bean into a @Bean annotated bean - BeanNotFoundException occurring

I didn't want to have to ask a question on here, but I've had a look at over 20 other similar issues on Stack Overflow, and none of them seem to be the exact same scenario!

I have a @Service annotated bean ( Service1.java ) which I am trying to autowire into another service ( Service2.java ) - the problem is that Service2 is annotated with the @Bean annotation rather than the @Service annotation because the subclass that gets instantiated can change depending on a certain database configuration. Here is the related code:

ApplicationConfig.java

@Configuration
public class ApplicationConfig {

    @Bean
    public Service2 service2() throws Exception {
        String className = Config.getString("service2.class");
        return (Service2) Class.forName(className).newInstance();
    }
}

Service1.java

@Service
public class Service1 {
    ....
}

Service2.java

public class Service2 {
    private @Autowired Service1 service1;
    ...
}

Interestingly, autowiring Service1 into another @Service annotated bean ( Service3.java ) works completely fine, so I know the bean is getting initialised ok. Eg

Service3.java

@Service
public class Service3 {
    private @Autowired Service1 service1;
}

Can anyone see anything obvious here? Unfortunately we have a mixture of XML and annotation based bean instantiations (trying to move across to annotations is a slow process as we're still on Spring 3.2!), so the component scanning, etc is done in an XML context file.

Interestingly, when trying to debug the situation, I printed out the list of Spring beans initialised at the point of setting the application context, and then upon loading the landing page of the web application (after commenting out the autowiring of Service1 in Service2 of course), and the @Service annotated beans only appeared in the latter list. So does this imply my problem is that the @Service annotated beans are always initialised after @Bean annotated beans, hence why I'm getting my exception upon startup? Here's the exception for completeness:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.eo3.eo3app.spring3.util.Service1] 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)}

Please let me know if I need to add any other details. I would obviously like to be able to annotate all my service classes with the @Service annotation, but don't know how to do this in the scenario where the subclass returned can be different each time you start the app up (like with Service2.java ).

I almost forgot to mention that the autowiring actually worked when I changed Service1.java from being a @Service annotated bean to initialising it as a @Bean annotated bean just like Service2.java .

Thanks very much in advance!

The problem in your case is the use of Class.forName to load and instantiate the service object. In this case the Autowiring capabilities will not work as it is not instantiated by the Spring Application context. You need to manually autowire using the following code.

@Configuration
public class ApplicationConfig {

    @Bean
    public Service2 service2(ApplicationContext applicationContext) throws Exception {
        String className = Config.getString("service2.class");
        Service2 service2Impl = (Service2) Class.forName(className).newInstance();

        applicationContext.getAutowireCapableBeanFactory().autowireBean(service2Impl);

        return service2Impl;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM