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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25683627/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 00:54:51  来源:igfitidea点击:

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

javaspringspring-mvc

提问by black_belt

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

  1. com.spring.org

    文件: HomeController.java

  2. com.spring.org.dao

    文件:SubscriberDao.javaSubscriberDaoImpl.java

  3. com.spring.org.model

    文件: Subscriber.java

  4. com.spring.org.service

    文件:SubscriberService.javaSubscriberServiceImpl.java

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

我将所有控制器类放在com.spring.org包中,其他类根据其类型放在不同的包中。如果我运行我的应用程序,我会收到此错误消息:

HTTP Status 500 - Servlet.init() for servlet appServlet threw exceptionNo 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 依赖项:预计至少有 1 个 bean 有资格作为此依赖项的自动装配候选... ..

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.orgpackage 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; 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)

org.springframework.beans.factory.BeanCreationException:创建名为“homeController”的 bean 时出错:自动装配依赖项的注入失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配字段:私有 com.spring.service.SubscriberService com.spring.org.HomeController.subService; 嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException: 找不到类型为 [com.spring.service.SubscriberService] 的合格 bean 依赖项:预期至少有 1 个 bean 有资格作为此依赖项的自动装配候选者。依赖注解:{@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=)} org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor .

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.

如果我将所有代码粘贴在这里,将很难遵循,因此我将整个项目上传到这里https://www.mediafire.com/?crxe7vt7uwyqwtl。我正在使用 Eclipse IDE。

采纳答案by Ashish Jagtap

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

主控制器.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 SubscriberServiceImplclass is under package com.spring.org.servicejust change your base package with com.springthis will work for you

根据您的包结构,您的SubscriberServiceImpl类位于包com.spring.org.service 下,只需使用com.spring更改您的基本包,这对您有用

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

回答by villager

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.

我相信你应该注释实现类而不是接口。

回答by Darshan Lila

The problem is you are having multiple implementation of SubscriberServiceinterface.

问题是您有多个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 @Qualifierto differentiate between different implementations.

对此的解决方案是使用@Qualifier区分不同的实现。

For more and for a demo on @Qualifiervisit thislink.

有关更多信息和演示,@Qualifier请访问链接。

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

或者,如果您有一个单一的实现,SubscriberService以确保服务和实现都属于您在 spring 上下文中为扫描提供的包。

Hope it helps.

希望能帮助到你。

回答by R_J

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" />

回答by Xstian

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 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 e.g. if I have to communicate to the database, have some transactions, etc.

根据我的经验,我总是在接口或抽象类上使用 @Service 注释,并使用 @Component 和 @Repository 等注释来实现它们。@Component 注释我在那些服务于基本目的的类上使用,简单的 Spring bean,仅此而已。我在 DAO 层中使用的 @Repository 注释,例如,如果我必须与数据库通信,进行一些事务等。

回答by m b

Specify the base scan as follows and remove the annotation from interface and keep only in the implementation class e.g. @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. Kindly change the package to com.spring.org.service.

但是您的 SubscriberService.java 在包 com.spring.service 中。请将包更改为 com.spring.org.service。

回答by Seif Tamallah

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. If it finds two such beans you will get an Exception ( it is the same one in your stack trace).

因为 Spring 搜索类型为SubscriberService(在您的情况下)的 bean,如果找到这样的 bean,它会将其注入此方法。如果它找到两个这样的 bean,你会得到一个异常(它在你的堆栈跟踪中是同一个)。

f you don't want to use two annotations (the @Autowiredand @Qualifier) you can use @Resourceto combine these two:

如果您不想使用两个注释(@Autowired@Qualifier),您可以@Resource将这两个注释结合起来:

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