0

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

网络服务 --> 服务层 --> 域层

在服务层,服务用 注释@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 文档中的一个相关部分:

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

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

任何想法?

谢谢


编辑:我只有一个上下文文件,它位于src/main/webapp/WEB-INF. 在这种情况下,我启用了类路径扫描,如下所示:

<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 服务实现类中,对服务的引用使用了实现类而不是接口。我只是将它们更改为使用界面,我不再遇到问题了。谁能解释一下使用服务实现类而不是自动装配接口有什么问题?

4

3 回答 3

2

这是您编辑的答案:

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

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

于 2012-08-28T20:18:06.487 回答
0

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

你想要这样的东西:

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

编辑:

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

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

@Autowired
private ExampleService service;

或者

@Autowired
private ExampleServiceImpl service;
于 2012-08-28T15:32:01.273 回答
0
  1. 确保你使用<context:component-scan base-package="your.service.package"/>
  2. 检查您的自动连线策略是byNamebyType;如果byNameService注解的名称值应该是正确的。
  3. 如果问题仍然存在,检查spring的日志,它会打印所有找到的组件的名称,你可以知道服务是否建立。
于 2012-08-28T15:39:03.203 回答