首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >缺少Spring依赖项但日志和调试状态已被实例化

缺少Spring依赖项但日志和调试状态已被实例化
EN

Stack Overflow用户
提问于 2016-05-07 15:04:03
回答 1查看 1.7K关注 0票数 2

我使用SpringBoot1.3.4.RELEASE和Spring4.2.6.RELEASE。

我有以下课程:

代码语言:javascript
复制
@Component
class ServerRunner implements Runnable {

与Constructor:

代码语言:javascript
复制
 @Autowired
  ServerRunner(@Value(HEARTBEAT_SECONDS) final long secondsBetweenHeartbeats,
               final ServerSocket socket,
               final PlayerRepository playerRepository,
               final DeckProcessor deckProcessor) {
    this.serverSocket = socket;
    this.maintainer = new Maintainer(secondsBetweenHeartbeats);
    this.playerRepository = playerRepository;
    final ExecutorService executorService = newCachedThreadPool();
    executorService.execute(this);
    this.running = true;

    this.deckProcessor = deckProcessor;
    executorService.execute(maintainer);
  }

当我启动我的应用程序时,它找不到依赖DeckProcessor

代码语言:javascript
复制
@Component
class DeckProcessor extends AbstractPlayerProcessor {
  private final DeckRepository repository;

  @Autowired(required = true)
  DeckProcessor(final DeckRepository repository) {
    super(QUERY_DECKS);
    this.repository = repository;
  }

引发以下异常:

代码语言:javascript
复制
  23:12:42 ERROR org.springframework.boot.SpringApplication - Application startup failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'serverRunner' defined in file [GameServer\arml-server\build\classes\main\com\arml\services\ServerRunner.class]: Unsatisfied dependency expressed through constructor argument with index 3 of type [com.arml.services.DeckProcessor]: No qualifying bean of type [com.arml.services.DeckProcessor] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.arml.services.DeckProcessor] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766) ~[spring-boot-1.3.4.RELEASE.jar:1.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361) [spring-boot-1.3.4.RELEASE.jar:1.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-1.3.4.RELEASE.jar:1.3.4.RELEASE]
    at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:134) [spring-boot-1.3.4.RELEASE.jar:1.3.4.RELEASE]
    at com.arml.ArmlServer.main(ArmlServer.java:21) [main/:?]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.arml.services.DeckProcessor] 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:1373) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    ... 17 more

但“日志”明确指出:

代码语言:javascript
复制
16:44:05 DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean deckProcessor
16:44:05 DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean deckProcessor
16:44:05 DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'deckProcessor' via constructor to bean named 'deckRepository'
16:44:05 DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Eagerly caching bean 'deckProcessor' to allow for resolving potential circular references
16:44:05 DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Finished creating instance of bean 'deckProcessor'

两个类驻留在同一个包中。

我做错了什么?我已经调试了几个小时了,一直找不到解决方案。

SpringBoot应用程序:

代码语言:javascript
复制
@EnableJpaRepositories(basePackages = "com.arml.persistence.repositories")
@EnableTransactionManagement
@SpringBootApplication
public class ArmlServer {

  public static void main(final String[] args) {
    new SpringApplicationBuilder()
        .web(false)
        .bannerMode(OFF)
        .sources(ArmlServer.class)
        .run(args);
  }
}

配置:

代码语言:javascript
复制
@Configuration
public class ArmlConfiguration {
  private static final Base64.Decoder DECODER = getDecoder();

  @Bean
  public ServerSocket armlSslSocket(@Value("${arml.server.bind-address}") final String bindAddress,
                                    @Value("${arml.server.port}") final int port,
                                    @Value("${arml.ssl.password}") final String password)
      throws IOException {
    final String keyPass = new String(DECODER.decode(password), UTF_8);
    return createServerSocket(bindAddress, port, keyPass);
  }

  @Bean
  public DataSource dataSource(final DataSourceProperties dataSourceProperties)
      throws PropertyVetoException {
    final ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setDriverClass(dataSourceProperties.getDriverClassName());
    dataSource.setUser(dataSourceProperties.getUsername());
    dataSource.setPassword(new String(DECODER.decode(dataSourceProperties.getPassword()), UTF_8));
    dataSource.setJdbcUrl(dataSourceProperties.getUrl());
    return dataSource;
  }
}

编辑:项目结构

Edit2:我确实尝试过@Gemini的建议。ServerRunner现在看起来如下(为了简洁起见,我移除了一些常量/方法):

代码语言:javascript
复制
@Component
@DependsOn("deckProcessor")
class ServerRunner implements Runnable {    

  @Value(HEARTBEAT_SECONDS)
  private long secondsBetweenHeartbeats;
  private Maintainer maintainer;
  @Autowired
  private ServerSocket serverSocket;
  @Autowired
  private PlayerRepository playerRepository;
  @Autowired
  private DeckProcessor deckProcessor;

  ServerRunner() {
  }

  @PostConstruct
  void init() {
    this.maintainer = new Maintainer(secondsBetweenHeartbeats);
    final ExecutorService executorService = newCachedThreadPool();
    executorService.execute(this);
    this.running = true;

    executorService.execute(maintainer);
  }

但例外情况仍然是:

代码语言:javascript
复制
07:12:36 ERROR org.springframework.boot.SpringApplication - Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serverRunner': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.arml.services.DeckProcessor com.arml.services.ServerRunner.deckProcessor; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.arml.services.DeckProcessor] 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:334) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766) ~[spring-boot-1.3.4.RELEASE.jar:1.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361) [spring-boot-1.3.4.RELEASE.jar:1.3.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-1.3.4.RELEASE.jar:1.3.4.RELEASE]
    at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:134) [spring-boot-1.3.4.RELEASE.jar:1.3.4.RELEASE]
    at com.arml.ArmlServer.main(ArmlServer.java:20) [main/:?]
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.arml.services.DeckProcessor com.arml.services.ServerRunner.deckProcessor; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.arml.services.DeckProcessor] 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:573) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    ... 15 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.arml.services.DeckProcessor] 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.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    ... 15 more

我还重新检查了注释,它们是:

代码语言:javascript
复制
import org.springframework.stereotype.Component;

一旦我移除deckProcessor,构造函数注入就能工作。真让人费解!

Edit3:我是个白痴。参数应该具有接口类型。将构造函数更改为:

代码语言:javascript
复制
  @Autowired
  ServerRunner(@Value(HEARTBEAT_SECONDS) final long secondsBetweenHeartbeats,
               final ServerSocket armlSslSocket,
               final PlayerRepository playerRepository,
               final Processor<ServerClientHandler> deckProcessor) {
    this.serverSocket = armlSslSocket;
    this.maintainer = new Maintainer(secondsBetweenHeartbeats);
    this.playerRepository = playerRepository;
    final ExecutorService executorService = newCachedThreadPool();
    executorService.execute(this);
    this.running = true;

    this.deckProcessor = deckProcessor;
    executorService.execute(maintainer);
  }

效果很好。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-05-08 00:49:46

这似乎是一个初始化依赖问题。请尝试将@DependsOn@Component一起用于ServerRunner类,如下所示:

代码语言:javascript
复制
@DependsOn(value = "deckProcessor")
@Component

value是指DeckProcessor的bean名称,默认情况下它总是deckProcessor。但是,可以通过在@Component(value = 'nameOfYourBean')上指定名称来命名它。

在您的示例中,您的构造函数需要自动生成一个DeckProcessor,这对于实例化ServerRunner bean来说太严格了,这意味着在创建ServerRunner时必须有一个ServerRunner bean。否则,无法实例化ServerRunner。但是,您可以通过创建一个ServerRunner方法来初始化@PostConstruct,并将代码从构造函数移到它中。例如:

代码语言:javascript
复制
@Value(HEARTBEAT_SECONDS)
long secondsBetweenHeartbeats;
@Autowired
ServerSocket socket;
@Autowired
PlayerRepository playerRepository;
@Autowired
DeckProcessor deckProcessor;
@PostConstruct
public void init() {
  this.serverSocket = socket;
  this.maintainer = new Maintainer(secondsBetweenHeartbeats);
  this.playerRepository = playerRepository;
  final ExecutorService executorService = newCachedThreadPool();
  executorService.execute(this);
  this.running = true;

  this.deckProcessor = deckProcessor;
  executorService.execute(maintainer);
}

此时,spring可以实例化所有bean,然后继续逐个初始化它们。应该管用的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37090075

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档