問題:在使用@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的情況。
希望各位老鐵后續遇到該問題的時候注意一下。