Spring原始碼系列:依賴注入-引言

glmapper發表於2018-02-03

在上面四篇文章中大概分析了一下Bean的載入,其實這個過程就是在Ioc容器中建立BeanDefinition的資料對映。但是對於Bean的例項化並未涉及,在之前的分析中也提到,bean的例項化是在依賴注入是才具體完成。

關於依賴注入

關於Spring,我們最先想到的就兩個Ioc和Aop;然後關於Ioc我們又能牽扯出兩個:控制反轉和依賴注入。 控制反轉和依賴注入在網上被無數大神亦或菜鳥解讀過,這裡就不羅列那些概念了,直接看:

不使用Spring

public class UserService {
    //手動new一個
    UserDao userDao = new UserDaoImpl();
    public int insertUser(String userName) {
    	return userDao.insertUser(userName);
    }
}
複製程式碼

使用Spring(以註解方式)

public class UserService {
    @Autowired
    private UserDao userDao;
    public int insertUser(String userName) {
    	return userDao.insertUser(userName);
    }
}
複製程式碼

看起來貌似沒有啥很大的改變,區別呢?

我們先來分析下在一個類中這兩種申明的區別:

UserDao userDao;

userDao是UserDao型別的引用名稱。僅僅是宣告瞭一個變數引用名稱。並沒有做例項化,userDao的例項化可以通過set方法進行設定(Spring中之前常用的就是set方法注入);當我們初始化持有userDao的這個類時我們還不知道userDao到底具體指向哪個堆中的物件地址。

UserDao userDao = new UserDaoImpl();

而這個,申明一個變數名稱,並將userDao直接指向new UserDaoImpl()建立的物件。

我們來看Spring中關於注入之後物件地址以及不使用注入方式物件的地址:

1、直接注入

Spring原始碼系列:依賴注入-引言
2、注入覆蓋了我自己的物件
Spring原始碼系列:依賴注入-引言
3、自己手動new
Spring原始碼系列:依賴注入-引言

通過上面三幅圖可以明顯的看出,自己手動new的物件沒有使用代理的方式,而託管給Spring注入的物件均是通過動態代理來完成的。

關於動態代理:《豬弟拱Java》連載番外篇:Java代理(中)

總結:當某個角色(可能是一個Java例項,呼叫者)需要另一個角色(另一個Java例項,被呼叫者)的協助時,在未使用Spring來管理Bean的程式設計過程中,通常由呼叫者來建立被呼叫者的例項。但在Spring裡,建立被呼叫者的工作不再由呼叫者來完成,因此稱為控制反轉;建立被呼叫者例項的工作通常由Spring容器來完成,然後注入呼叫者,因此也稱為依賴注入。

三個問題

那麼現在要考慮問題就是,什麼時候會觸發我們的依賴注入呢?Bean的例項化是否必須在依賴注入時才能完成呢?在Spring中又是通過哪些類來完成注入工作的呢?

1、什麼時候會觸發我們的依賴注入

答:使用者第一次向容器獲取Bean的時候出發。

2、Bean的例項化是否必須在依賴注入時才能完成

這個其實不是必須的,我們們都知道BeanDefinition中有lazy-init這樣一個屬性,我們可以通過控制這個屬性的設定來讓容器完成對Bean的預例項化。預例項化就是說它的依賴注入是在例項化過程中完成的。

第一和第二個問題將會在分析第三個問題的時候慢慢的細化分析。所以第三個問題其實沒啥鳥用,但也是最最最核心的,就是為了引出後面關於一些具體類的分析的。

相關文章