一、场景复现
报错日志
***************************
APPLICATION FAILED TO START
***************************Description:A component required a bean of type 'com.mk.service.TestService' that could not be found.Action:Consider defining a bean of type 'com.mk.service.TestService' in your configuration
@Service
public class TestService implements ITestService{@Asyncpublic Future<String> doActionAsync(){return new AsyncResult(doAction());}@Overridepublic String doAction() {return "done";}
}public interface ITestService {String doAction();
}@Component
public class Runner implements ApplicationContextAware {@EventListener(ApplicationReadyEvent.class)public void run(){TestService testService = applicationContext.getBean(TestService.class);testService.doActionAsync();}private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext =applicationContext;}
}@EnableAsync
@Configuration
@SpringBootApplication
public class ServiceApplication {public static void main(String[] args) {SpringApplication.run(ServiceApplication.class, args);}}
二、分析原因
(1)doActionAsync加上接口方法,执行一样报错
@Service
public class TestService implements ITestService{@Override@Asyncpublic Future<String> doActionAsync(){return new AsyncResult(doAction());}@Overridepublic String doAction() {return "done";}
}
(2)使用ITestService调用就不报错
@Component
public class Runner implements ApplicationContextAware {@EventListener(ApplicationReadyEvent.class)public void run(){ITestService testService = applicationContext.getBean(ITestService.class);testService.doActionAsync();}private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext =applicationContext;}
}
(3)Springboot 代理类型
Springboot 默认代理类型为jdk proxy
bean有实现接口使用jdk proxy代理,没有实现接口则使用cglib代理
三、解决方案
(1)将方法抽象到接口
(2)强制使用cglib代理
@EnableAsync(proxyTargetClass = true)
@Configuration
@SpringBootApplication
public class ServiceApplication {public static void main(String[] args) {SpringApplication.run(ServiceApplication.class, args);}}