简体   繁体   English

如果所有类不在同一个包中,则Spring @autowired不起作用

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

I have four packages: 我有四个包:

  1. com.spring.org com.spring.org

    Files: HomeController.java 文件: HomeController.java

  2. com.spring.org.dao com.spring.org.dao

    Files: SubscriberDao.java , SubscriberDaoImpl.java 文件: SubscriberDao.javaSubscriberDaoImpl.java

  3. com.spring.org.model com.spring.org.model

    Files: Subscriber.java 文件: Subscriber.java

  4. com.spring.org.service com.spring.org.service

    Files: SubscriberService.java , SubscriberServiceImpl.java 文件: SubscriberService.javaSubscriberServiceImpl.java

I put all my controller classes in com.spring.org package and others in different packages based on its type. 我将所有控制器类放在com.spring.org包中,其他包基于其类型放在不同的包中。 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..... HTTP状态500 - servlet appServlet的Servlet.init()抛出异常 没有找到依赖的类型[com.spring.org.service.SubscriberService]的限定bean:预期至少有一个bean有资格作为此依赖关系的autowire候选者... ..

FYI: I am using autowired annoation in my Controller like following: 仅供参考:我在我的控制器中使用自动装载的annoation,如下所示:

@Autowired
private SubscriberService subService;

But if I put all my classes and interfaces in com.spring.org package then my application works perfectly. 但是,如果我将所有类和接口放在com.spring.org包中,那么我的应用程序就可以完美运行。

I have tried using these tags in my servlet-context.xml file to solve the problem, but still it did not work: 我已经尝试在我的servlet-context.xml文件中使用这些标记来解决问题,但它仍然无效:

<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/ 你可以在这里看到我的servlet-context.xml文件的代码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 : 我的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; org.springframework.beans.factory.BeanCreationException:创建名为'homeController'的bean时出错:注入自动连接的依赖项失败; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.spring.service.SubscriberService com.spring.org.HomeController.subService; 嵌套异常是org.springframework.beans.factory.BeanCreationException:无法自动装配字段: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. 嵌套异常是org.springframework.beans.factory.NoSuchBeanDefinitionException:找不到[com.spring.service.SubscriberService]类型的限定bean用于依赖:预期至少有1个bean可以作为此依赖项的autowire候选者。 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) 依赖注释:{@ 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 . 如果我在这里粘贴所有代码,那将非常难以理解,所以我在这里上传了我的整个项目https://www.mediafire.com/?crxe7vt7uwyqwtl I am using Eclipse IDE. 我正在使用Eclipse IDE。

your structure should be like this 你的结构应该是这样的

SubscriberService Interface 订阅服务接口

package com.spring.org.service;

public interface SubscriberService {

}

SubscriberServiceImpl.java SubscriberServiceImpl.java

package com.spring.org.service;

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

}

'SubscriberServiceImpl1' is a component and it implements 'SubscriberService'. 'SubscriberServiceImpl1'是一个组件,它实现了'SubscriberService'。

SubscriberServiceImpl1.java 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'. 我设置了一个Spring上下文,它扫描这两个包中标有'@Component'的bean。

servlet-context.xml servlet的context.xml中

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

HomeController.java 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 根据您的包结构,您的SubscriberServiceImpl类位于包com.spring.org.service下,只需使用com.spring更改您的基本包,这将适合您

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

The problem is you are having multiple implementation of SubscriberService interface. 问题是您有多个SubscriberService接口的实现。

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. Spring将寻找SubscriberService的实现,因为你将有多个实现,spring将不知道要注入哪个实现。

Solution to this is using @Qualifier to differentiate between different implementations. 解决方案是使用@Qualifier来区分不同的实现。

For more and for a demo on @Qualifier visit this link. 有关@Qualifier更多信息和演示,请访问链接。

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. 或者,如果您有一个SubscriberService实现,请确保服务和实现都属于您在spring上下文中提供的扫描包。

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. 尝试在SubscriberServiceImpl上添加@Component。

Basically annotations like @Service, @Repository, @Component, etc. they all serve the same purpose: 基本上注释如@ Service,@ Repository,@ Component等,它们都有相同的用途:

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和@Repository)上使用@Service注释来实现它们。 @Component annotation I am using on those classes which serves basic purposes, simple Spring beans, nothing more. @Component注释我在那些用于基本目的的类上使用,简单的Spring bean,仅此而已。 @Repository annotation I am using in the DAO layer, for eg if I have to communicate to the database, have some transactions, etc. 我正在DAO层中使用的@Repository注释,例如,如果我必须与数据库通信,进行一些事务等。

Specify the base scan as follows and remove the annotation from interface and keep only in the implementation class eg @Service, @Repository, @Component, etc. 如下指定基本扫描并从接口中删除注释,并仅保留在实现类中,例如@ Service,@ Repository,@ Component等。

<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. 但是您的SubscriberService.java位于com.spring.service包中。 Kindly change the package to com.spring.org.service. 请将软件包更改为com.spring.org.service。

First you have to put this tag in your XML (application context file): 首先,您必须将此标记放在XML(应用程序上下文文件)中:

<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. 因为Spring会搜索SubscriberService类型的bean(在你的例子中),如果它找到了这样的bean,它会将它注入到这个方法中。 If it finds two such beans you will get an Exception ( it is the same one in your stack trace). 如果它找到两个这样的bean,你将得到一个Exception(它与你的堆栈跟踪中的相同)。

f you don't want to use two annotations (the @Autowired and @Qualifier ) you can use @Resource to combine these two: 如果您不想使用两个注释( @Autowired@Qualifier ),您可以使用@Resource来组合这两个:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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