我有一个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文档中的一个相关部分:
类路径包的扫描需要存在 类路径中的相应目录条目。构建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服务(com.mycompany.project.server
),服务层(com.mycompany.project.services
)和域层({ {1}})包。
我已经解决了这个问题。我不明白为什么我所做的是造成这样的问题。每个服务都实现一个定义其公共方法的接口。在我的Web服务实现类中,对服务的引用使用了实现类而不是接口。我只是将它们改为使用界面,我不再讨论这个问题了。任何人都可以解释一下使用服务实现类而不是自动装配接口有什么问题吗?
答案 0 :(得分:2)
这是您编辑的答案:
为什么引用接口工作但具体实现失败的原因可能与Spring为您使用@Transactional
注释服务的情况创建的dynamic proxies等有关。例如,bean的类型不再是实现类型,而是包裹您的实现类型。因此,当您通过实现类型获得@Autowired时,它无法按类型找到它(这是默认值)。
您的修复非常合适,因为动态代理继续从您为实现定义的接口派生,因此可以通过接口类型注入 - 我提供的引用可以更好地解释这一点。
答案 1 :(得分:0)
您能展示您的组件扫描配置吗?如果设置不正确,那么Spring可能无法发现您的服务。
你想要这样的东西:
<context:component-scan base-package="your.service.package"/>
修改强>
我认为问题在于你的@Service
注释是在接口而不是实现类上。
如果您注释了您的服务实现,那么您的Web控制器可以使用:
@Autowired
private ExampleService service;
或
@Autowired
private ExampleServiceImpl service;
答案 2 :(得分:0)
<context:component-scan base-package="your.service.package"/>
byName
还是byType
;如果byName
,则Service
注释的名称值应该是正确的。