简体   繁体   中英

Spring @autowired do not work if all classes are not in the same package

I have four packages:

  1. com.spring.org

    Files: HomeController.java

  2. com.spring.org.dao

    Files: SubscriberDao.java , SubscriberDaoImpl.java

  3. com.spring.org.model

    Files: Subscriber.java

  4. com.spring.org.service

    Files: SubscriberService.java , SubscriberServiceImpl.java

I put all my controller classes in com.spring.org package and others in different packages based on its type. If I run my application I get this error message :

HTTP Status 500 - Servlet.init() for servlet appServlet threw exception No qualifying bean of type [com.spring.org.service.SubscriberService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.....

FYI: I am using autowired annoation in my Controller like following:

@Autowired
private SubscriberService subService;

But if I put all my classes and interfaces in com.spring.org package then my application works perfectly.

I have tried using these tags in my servlet-context.xml file to solve the problem, but still it did not work:

<annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.spring.org.**" />
<context:component-scan base-package="com.spring.org.dao" />
<context:component-scan base-package="com.spring.org.model" />
<context:component-scan base-package="com.spring.org.service" />

I also tried only this:

<context:component-scan base-package="com.spring.org" />

You can see the code of my servlet-context.xml file here http://postimg.org/image/s6bnjccrn/

Could you please tell me how to solve this problem ?

Please let me know if you need to see any other files.

Update

My Code for SubscriberService :

@Service
public interface SubscriberService {

 public void addSubscriber(Subscriber subscriber);
 public void updateSubscriber(Subscriber subscriber);
 public Subscriber getSubscriberById(int subId);
 public List<Subscriber> listSubs();
 public int removeSubscriber(int subId);    

}

Root Cause

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.spring.service.SubscriberService com.spring.org.HomeController.subService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.spring.service.SubscriberService] 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), @org.springframework.beans.factory.annotation.Qualifier(value=)} org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)

Files

It would be very difficult to follow if I paste all my codes here, so I have upload my entire project here https://www.mediafire.com/?crxe7vt7uwyqwtl . I am using Eclipse IDE.

your structure should be like this

SubscriberService Interface

package com.spring.org.service;

public interface SubscriberService {

}

SubscriberServiceImpl.java

package com.spring.org.service;

@Component
@Qualifier("Subscriber")
public class SubscriberServiceImpl implements SubscriberService {

}

'SubscriberServiceImpl1' is a component and it implements 'SubscriberService'.

SubscriberServiceImpl1.java

package com.spring.org.service;

@Component
@Qualifier("Subscriber1")
public class SubscriberServiceImpl1 implements SubscriberService {

}

I setup a Spring context that scans both of these packages for beans marked with '@Component'.

servlet-context.xml

<annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.spring"/>

HomeController.java

@Controller
public class HomeController {

    @Autowired
    @Qualifier("Subscriber")
    private SubscriberService subService;

}

refer from this link . hope this will help you....

EDIT

as per your package structure your SubscriberServiceImpl class is under package com.spring.org.service just change your base package with com.spring this will work for you

<context:component-scan base-package="com.spring"/>

The problem is you are having multiple implementation of SubscriberService interface.

When you write following code:

@Autowired
private SubscriberService subService;

Spring will look for an implementation of SubscriberService , and since you would be having multiple implementation for it spring will not know which implementation to inject.

Solution to this is using @Qualifier to differentiate between different implementations.

For more and for a demo on @Qualifier visit this link.

Alternatively if you're having a single implementation for SubscriberService make sure both the service and implementation fall under the packages you provide for scan in spring context.

Hope it helps.

You just need to specify the base package:

<context:component-scan base-package="com.spring.org"/>

I believe you should annotate the implementation class instead of the interface.

Try comma-separating the packages, like this:

<context:component-scan 
base-package="com.spring.org,com.spring.org.dao,com.spring.org.model,com.spring.org.service" />

Try to add @Component on SubscriberServiceImpl.

Basically annotations like @Service, @Repository, @Component, etc. they all serve the same purpose:

auto-detection when using annotation-based configuration and classpath scanning.

From my experience I am always using @Service annotation on the interfaces or abstract classes and annotations like @Component and @Repository for their implementation. @Component annotation I am using on those classes which serves basic purposes, simple Spring beans, nothing more. @Repository annotation I am using in the DAO layer, for eg if I have to communicate to the database, have some transactions, etc.

Specify the base scan as follows and remove the annotation from interface and keep only in the implementation class eg @Service, @Repository, @Component, etc.

<context:component-scan base-package="com.spring.org"/> 

EDIT:

I looked into your code.You have given your component scan as

But your SubscriberService.java is in the package com.spring.service. Kindly change the package to com.spring.org.service.

First you have to put this tag in your XML (application context file):

<context:component-scan base-package="com.spring.org"/>

To fix the expection you got you have to change this :

@Autowired
@Qualifier("Subscriber")
private SubscriberService subService

because Spring searches for a bean of type SubscriberService (in your case), and if it finds such bean, it injects it to this method. If it finds two such beans you will get an Exception ( it is the same one in your stack trace).

f you don't want to use two annotations (the @Autowired and @Qualifier ) you can use @Resource to combine these two:

@Resource(name="redBean")
private SubscriberService subService

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