【问题标题】:@ComponentScan and @Autowired fail to inject from a specific package@ComponentScan 和 @Autowired 无法从特定包注入
【发布时间】:2015-01-23 09:11:30
【问题描述】:

我知道关于这个问题的许多类似问题,但是,没有一个解决了我的问题。我有一个 Spring REST 项目,我正在使用 Spring Tool Suite (STS) 3.5.1 RELEASE。

应用类:

package com.example.rest;

@ComponentScan({"com.example.repositories", "com.example.config", "com.example.services",    "com.example.rest", "com.example.jms"})
@EnableAutoConfiguration
public class Application 
{
  ... //declaring some beans for JMS
}

存储库类:

package com.example.repositories;

@Repository
public interface ActorRepository extends MongoRepository<Actor, String> 
{

   public Actor findByFNameAndLName(String fName, String lName);
   public Actor findByFName (String fName);
   public Actor findByLName(String lName);

}

Service 类(此处Autowire 无法注入actorRepository):

package com.example.services;

@Service
public class ActorService 
{
  @Autowired
  private ActorRepository actorRepository;
  ....
}

REST 服务(Autowired 注入 actorService 失败 - 我认为是因为 ActorService 未能注入 ActorRepository):

package com.example.rest;

@RestController
@RequestMapping("/actors")

public class ActorRESTService 
{
  private static final Logger logger = Logger.getLogger(ActorRESTService.class);

  @Autowired 
  private ActorService actorService;

  ....
}

我认为这是因为@ComponentScan 没有扫描存储库包的原因是在 STS 中,Spring 类在其 Java 图标的右上角有一个小 S。这出现在应该扫描的所有类上(除了存储库包中的任何内容之外的组件)。将存储库类移动到 rest 包会使它们被扫描(不知道为什么!)。

这是我尝试使用 Spring Boot App 运行项目时遇到的问题的一部分。

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'actorService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.example.repositories.ActorRepository com.example.services.ActorService.actorRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.repositories.ActorRepository] 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)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:120)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:683)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:313)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:944)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:933)
at com.example.rest.Application.main(Application.java:94)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.example.repositories.ActorRepository com.example.services.ActorService.actorRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.repositories.ActorRepository] 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)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
... 16 common frames omitted

 .....  

【问题讨论】:

  • 存储库必须在同一个包或主(应用程序)类的子包中。这是 Spring Boot 中的默认行为。
  • 谢谢@Evgeni。实际上,我之前有过这样的设置并且它正在工作。但是将存储库移动到自己的包中以保持清洁。将它们保留在主类中的逻辑是什么?
  • 为了保持干净,您还可以将 repos 放在子包中,例如 com.example.rest.repo 在您的情况下。
  • @Evgeni 您的第一条和第二条评论听起来像是一个答案。我建议把它变成一个,以便 OP 可以标记它。
  • Application 类移动到com.example。这样,您甚至可以从 @ComponentScan 中删除所有内容,只需留下空注释即可。自动启用的 spring 数据 mongoldb 的默认行为是扫描与启动应用程序(及其子包)相同的包中的存储库。我只是将应用程序类放在主包中,以便自动覆盖所有内容。

标签: java spring rest autowired component-scan


【解决方案1】:

存储库必须在同一个包或主(应用程序)类的子包中。这是 Spring Boot 中的默认行为。为了保持干净,您还可以将存储库放在子包中,例如 com.example.rest.repo 在您的情况下。或者正如 M. Deinum 建议的那样,您可以将主类放在基础包中,以便 spring 可以自动处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-19
    • 1970-01-01
    • 2021-11-14
    • 2015-04-12
    • 2022-01-12
    相关资源
    最近更新 更多