由於@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的情況。

 希望各位老鐵后續遇到該問題的時候注意一下。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM