【问题标题】:Classpath scanning of dependencies依赖项的类路径扫描
【发布时间】:2012-08-29 05:35:24
【问题描述】:

我有一个 3 层应用程序:Web 服务、服务层和域层。 Web 服务存在于 Web 应用程序 (WAR) 中。服务层和领域层是两个 JAR 项目。依赖项是:

web-service --> 服务层 --> 域层

在服务层,服务用@Service注解。在域层中,DAO 使用@Repository 进行注释。 Web 服务实现类使用服务层 JAR 的服务,因此它为每个自动注入的服务保留一个实例(@Autowired)。

在我的 POM 中明确定义了依赖项。当我在 Tomcat 上部署 WAR 时,出现以下异常:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.mycompany.project.services.MyService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:952)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:821)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:735)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:551)
    ... 37 more

我引用了 Spring 文档中的一个相关部分:

类路径包的扫描需要存在 类路径中的相应目录条目。构建 JAR 时 使用 Ant 时,请确保您没有激活仅文件开关 JAR 任务。

我已经检查过,服务层 JAR 存在于 WEB-INF/lib 目录中。

有什么想法吗?

谢谢


编辑: 我只有一个上下文文件,它位于src/main/webapp/WEB-INF 下的 Web 服务层项目 (WAR) 中。在这种情况下,我启用了类路径扫描,如下所示:

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

com.mycompany.project是我项目的基础包,下面有web-service(com.mycompany.project.server)、service-layer(com.mycompany.project.services)和domain-layer(com.mycompany.project.domain)包。

我已经解决了这个问题。我不明白为什么我所做的会导致这样的问题。每个服务都实现了一个定义其公共方法的接口。在我的 Web 服务实现类中,对服务的引用使用了实现类而不是接口。我只是将它们更改为使用界面,我不再遇到问题了。谁能解释一下使用服务实现类而不是自动装配接口有什么问题?

【问题讨论】:

  • 这里可能会发生很多事情。一种可能的可能性是您的 Web 层上下文对服务层上下文一无所知。或者您没有在服务层上下文中进行组件扫描。要回答这些问题,您需要发布您的上下文文件。
  • 请贴出你配置组件扫描的spring配置部分。
  • 另外:查看异常报告的结尾。 Spring 递归地报告 bean 实例化失败,报告中的最后一个 bean 是问题所在(它阻止实例化报告中更高的任何 bean)。
  • 我已经编辑了我的问题。

标签: java spring


【解决方案1】:

这是您编辑的答案:

引用接口有效但具体实现失败的原因可能与 Spring 创建的 dynamic proxies 相关,在这种情况下,您的服务使用 @Transactional 等注释。在这种情况下发生的情况是您的 bean 类型不再是实现类型,而是围绕您的实现类型。因此,当您按实现类型拥有@Autowired 时,它只是无法按类型找到它(这是默认设置)。

您的修复非常合适,因为动态代理继续从您为实现定义的接口派生,因此可以按接口类型注入 - 我提供的参考可以更好地解释这一点。

【讨论】:

    【解决方案2】:
    1. 确保您使用了&lt;context:component-scan base-package="your.service.package"/&gt;
    2. 检查您的自动连线策略是byNamebyType;如果byName,则Service注解的名称值应该是正确的。
    3. 如果问题仍然存在,查看spring的日志,它会打印所有找到的组件的名称,你可以知道服务是否建立。

    【讨论】:

    • 我已经编辑了我的问题。我已经在基础包(它应该包括包含我的服务的包)上启用了类路径扫描。我没有在服务注释中指定名称,但默认情况下,Spring 采用相同的名称,但第一个字母小写。
    【解决方案3】:

    您能展示一下您的组件扫描配置吗?如果设置不正确,那么 Spring 可能不会发现您的服务。

    你想要这样的东西:

    <context:component-scan base-package="your.service.package"/>
    

    编辑:

    我认为问题在于您的@Service 注释在接口而不是实现类上。

    如果您注释您的服务实现,那么您的网络控制器可以使用:

    @Autowired
    private ExampleService service;
    

    @Autowired
    private ExampleServiceImpl service;
    

    【讨论】:

    • 关于您对我的编辑的回答,@Service 注释过去和现在都放在实现类上,而不是在接口上。
    猜你喜欢
    • 2022-01-22
    • 2021-01-29
    • 2019-08-12
    • 2014-05-28
    • 1970-01-01
    • 1970-01-01
    • 2018-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多