1.對於新手來說,最明顯的不過是在applicationContext.xml文件上沒有加<context:component-scan base-package="com.xxx"/>,或者明明寫了,但Spring還是沒有將該類注入到容器中.其實,很多人都喜歡將包的路徑寫的非常的詳細,比如:com.xxx.xxx.service等,這樣做的好處是Spring啟動的時候,掃描的類更少了,效率更高了.這樣做其實無可厚非,但是有些時候,你難免會把所有需要交給Spring管理都放在這個包下,這就導致有些放在其它包下的,貼有@Controller,@Service,@Repository,@Component等注解的類也不會交給Spring管理了.所以,最穩妥的方法就是,掃描所有的包,如下
對於使用idea的同學來說,想要知道有沒有掃描到你想要的類,可以直接點擊這個配置旁邊類似葉子的圖標,那里可以看到當前所有被Spring所管理的類.
2.主要說一下本人最近遇到的一個比較常識性但又容易踩坑的地方,我們都知道,如果你想要通過@Autowired注入一個對象,那么前提是當前你所在的這個類本身需要被Spring管理, 舉個例子: 你想要在一個Controller里注入一個Service,那么不僅這個Service要貼上@Service,這個Controller也要貼上@Controller, 如果當前的Controller並未貼上@Controller,那就無法注入,因為Spring並未管理當前Controller的生命周期.
重點來了,如果我的一個Service A明明已經貼上了注解,另一個Service B也貼上了注解,而且都被掃描到了,那為什么還是無法通過@Autowired注入呢?
原理其實很簡單, 在SMSImpl里要調用receiptService的方法,首先SMSImpl這個類就要從容器中拿,而不能直接new出來,因為交給Spring管理的類一般默認是單例的,它會為這個對象注入屬性,但自己new出來的類,就不會注入這個屬性了,而我拿到的SMSImpl實現類其實就是我自己new出來的.
如圖,在某個類中,啟動容器先加載靜態代碼塊的時候,把所有實現了IMessageSMS接口的類都放入在一個Map中,而這些類其實都是newInstance出來的,所以這些類本身是沒有屬性的對象的,所以在調用的時候,就為null了,而解決的辦法也很簡單,直接去容器中拿出receiptService對象即可.