@ComponentScan и @Autowired не могут выполнить инъекцию из определенного пакета

Я знаю о многих подобных вопросах по этой проблеме на SO, однако ни один из них не решил мою проблему. У меня есть проект 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);

}

Класс службы (здесь Autowire не может внедрить actRepository):

package com.example.services;

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

Служба REST (Autowired не может внедрить actService - я предполагаю, что это потому, что 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 имеют маленькую букву S в правом верхнем углу значка Java. И это проявляется во всех классах, которые следует сканировать (компоненты, за исключением всего, что находится в пакете репозиториев). Перемещение классов репозитория в оставшийся пакет приводит к их сканированию (не знаю, почему!).

Это часть исключения, которое я получаю, когда пытаюсь запустить проект с помощью приложения Spring Boot.

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

 .....  

person Sami    schedule 25.11.2014    source источник
comment
Репозитории должны находиться в том же пакете или подпакете основного (приложения) класса. Это поведение по умолчанию при весенней загрузке.   -  person Evgeni Dimitrov    schedule 25.11.2014
comment
Спасибо @Евгений. На самом деле, у меня была такая установка раньше, и она работала. Но переместил репозитории в свой собственный пакет, чтобы сохранить чистоту. Какова логика сохранения их в основном классе?   -  person Sami    schedule 25.11.2014
comment
Чтобы все было чисто, вы также можете поместить репозитории в дополнительный пакет, например com.example.rest.repo в вашем случае.   -  person Evgeni Dimitrov    schedule 25.11.2014
comment
@Evgeni, ваш первый и второй комментарий звучат как ответ. Я бы предложил превратить его в один, чтобы ОП мог его пометить.   -  person Erwin Bolwidt    schedule 25.11.2014
comment
Переместите класс Application в com.example. Таким образом, вы даже можете удалить все из @ComponentScan, просто оставив пустую аннотацию. Поведение по умолчанию для автоматически включенных данных spring mongoldb заключается в сканировании репозиториев в том же пакете, из которого было запущено приложение (и его подпакеты). Я бы просто поместил класс приложения в основной пакет, чтобы все покрылось автоматически.   -  person M. Deinum    schedule 25.11.2014


Ответы (1)


Репозитории должны находиться в том же пакете или подпакете основного (приложения) класса. Это поведение по умолчанию при весенней загрузке. Чтобы все было чисто, вы также можете поместить репозитории в дополнительный пакет, например com.example.rest.repo в вашем случае. Или, как предложил М. Дейнум, вы можете поместить основной класс в базовый пакет, чтобы Spring мог обрабатывать это автоматически.

person Evgeni Dimitrov    schedule 25.11.2014