记@ConditionalOnMissingBean注解导致bean注入失败的问题

1.背景

springboot项目,引入nacos做配置中心,pom.yaml导入依赖

        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>nacos-config-spring-boot-starter</artifactId>
            <version>0.2.12</version>
        </dependency>

 

2.运行项目时报错如下:

***************************
APPLICATION FAILED TO START
***************************

Description:

Field threadPoolTaskExecutor in com.paas.dmp.server.job.state.job.JobStateSynService required a bean of type 'org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor' that could not be found.

The injection point has the following annotations:
	- @org.springframework.beans.factory.annotation.Autowired(required=true)
	- @org.springframework.beans.factory.annotation.Qualifier(value=applicationTaskExecutor)

The following candidates were found but could not be injected:
	- Bean method 'applicationTaskExecutor' in 'TaskExecutionAutoConfiguration' not loaded because @ConditionalOnMissingBean (types: java.util.concurrent.Executor; SearchStrategy: all) found beans of type 'java.util.concurrent.Executor' nacosConfigListenerExecutor


Action:

Consider revisiting the entries above or defining a bean of type 'org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor' in your configuration.


Process finished with exit code 1

 

3.原因分析

在springboot项目中注入TaskExecutionAutoConfiguration的配置如下:

    @Autowired
    @Qualifier(value = TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME)
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

 

根据上述报错描述可知:TaskExecutionAutoConfiguration自动配置类没有成功注入名称为applicationTaskExecutor的bean,因为@ConditionalOnMissingBean注解找到了Executor.class的bean。

查看TaskExecutionAutoConfiguration这个自动配置类的源码,关键代码如下:

    @Lazy
    @Bean(
        name = {"applicationTaskExecutor", "taskExecutor"}
    )
    @ConditionalOnMissingBean({Executor.class})
    public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {
        return builder.build();
    }

可以看到ThreadPoolTaskExecutor加上了@ConditionalOnMissingBean的注解,这个注解在这里的意思是:如果没有Executor的bean,就注入ThreadPoolTaskExecutor的bean。

当我们引入nacos的配置中心相关依赖时,会自动注入一个Executor的bean,名称为nacosConfigListenerExecutor,所以当我们在代码中再注入ThreadPoolTaskExecutor 的bean时就会有前面说到的报错。

 

4.问题解决

手动注入bean

 

    @Autowired
    @Qualifier(value = TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME)
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

//通过@Bean注解手动注入ThreadPoolTaskExecutor的bean @Bean(name
= TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME) public ThreadPoolTaskExecutor threadPoolTaskExecutor(){ return new ThreadPoolTaskExecutor(); }

 

 

5.引入nacos做配置中心其他注意事项

5.1.注意引入依赖的版本,nacos-config-spring-boot-starter版本太高可能会拉取不到nacos的配置;

5.2.nacos地址通过域名代理出来时,通过nacos的域名+api接口是可以拿到nacos的配置的,但是如果在springboot的配置文件里配置的nacos.server-addr的地址为域名时,是拿不到nacos上的配置的;

5.3.nacos配置中心配置的logging.config配置不生效,这可能与bootstrap.yml(bootstrap.properties)、application.yml(application.properties)的加载顺序有关,可以把logging.config的相关配置放到本地的配置文件中,不放到配置中心,这样也可以使相关配置生效。

 

参考:

https://blog.csdn.net/weixin_43916074/article/details/123951297

 

posted @ 2023-07-06 19:00  wdgde  阅读(1295)  评论(0)    收藏  举报