由于@Component和@Autowired的先后顺序问题导致的问题

问题:在使用@Autowired自动注入service的时候发现并未注入成功,得到的对象是null

排查过程:

1.开始怀疑是该service未实例化到spring容器中,或者该service存在问题,因此执行单元测试单独测试了该service:

 1 @RunWith(SpringJUnit4ClassRunner.class)
 2 @SpringBootTest(classes = Bootstrap.class)
 3 public class CacheTest {
 4     
 5     @Autowired
 6     private CacheService cacheService;
 7     
 8     @Test
 9     public void cacheTest(){
10         cacheService.createTable("trail01");
11     }
12 }

结果自然是毫无问题,可以正常使用,那么问题出现在哪里呢?

2.是否是这样,因为我有一个自定义的bean需要实例化到spring容器内,然后我再构造里面又使用了@Autowired ,这样做是不是存在什么问题,于是进行测试:

 1 @RestController
 2 @RequestMapping(value = "/api/task")
 3 public class TaskController {
 4     @Autowired
 5     private InitializeContext initializeContext;
 6     @Autowired
 7     private CacheService cacheService;
 8     
 9     @RequestMapping(value = "/",method = RequestMethod.POST)
10     public ResMessage<TaskContext> postTask(@RequestBody TaskContext context){
11         cacheService.createTable("test001");
12         return new ResMessage<TaskContext>(ResCode.Success);
13     }
14      
15 }

结果也毫无问题,那么基本可以排除我的service本身的问题了。

3.那么此时问题一定出在我的扫描和注入顺序上面,因为在使用@Component注解将bean实例化到spring容器内的时候,我的@Autowired是在这个bean之中的,所以一定出现了spring加载顺序的问题

 1 @Component
 2 public class InitializeContext {
 3     private IntegrationServerContext serverContext;
 4     private TaskProcessor taskProcessor;
 5     @Autowired
 6     private CacheService cacheService;
 7     
 8     InitializeContext() throws Exception{
 9         Configuration configuration = new PropertiesConfiguration("config.properties");
10         GenericCDIServer cdiServer = new GenericCDIServer(configuration);
11         cdiServer.start();
12         serverContext = new IntegrationServerContext(configuration);
13         serverContext.getFtpUserInfo().forEach((storeCode,password)->{
14             cacheService.createTable(storeCode);
15         });
16         if(serverContext.getSystemIntegrationMode().equals(IntegrationMode.EmbeddedFtp.getName())){
17             taskProcessor = new TaskProcessor(serverContext.getTaskProcessorNum(), serverContext);
18         }
19     }

当spring实例化该bean到容器内的时候,此时使用@Autowired怕是还未完成自动装载,所以导致我这里会出现null,于是,查看了spring的文档,修改为构造注入的方式如下:

 1 @Component
 2 public class InitializeContext {
 3     private IntegrationServerContext serverContext;
 4     private TaskProcessor taskProcessor;
 5     
 6     @Autowired
 7     InitializeContext(CacheService cacheService) throws Exception{
 8         Configuration configuration = new PropertiesConfiguration("config.properties");
 9         GenericCDIServer cdiServer = new GenericCDIServer(configuration);
10         cdiServer.start();
11         serverContext = new IntegrationServerContext(configuration);
12         serverContext.getFtpUserInfo().forEach((storeCode,password)->{
13             cacheService.createTable(storeCode);
14         });
15         if(serverContext.getSystemIntegrationMode().equals(IntegrationMode.EmbeddedFtp.getName())){
16             taskProcessor = new TaskProcessor(serverContext.getTaskProcessorNum(),serverContext, cacheService);
17         }
18     }

完美解决,再无任何异常,由此可以确认就是上述的问题, @Autowired 是要等待构造完成后才进行的,所以才会出现在构造中使用的时候会出现null的情况。

 希望各位老铁后续遇到该问题的时候注意一下。

猜你喜欢

转载自www.cnblogs.com/NeverHaveBugs/p/9120592.html