不知道各位還記不記得 Spring 對 bean 生命週期的管理方式:Spring 默認採用單例的方式管理 Bean,在獲取 Bean 實例的時候會經過一個緩存進行獲取,若是還未初始化,那麼就會先將 Bean Definition 進行一個初始化放入緩存,而後再經過緩存獲取。java
那麼在上一章中,我也在總結中提到過:在執行完 beanDefinitionReader.loadBeanDefinitions(resource);
這段代碼以後,僅僅是完成了 beanDefinition 的解析與註冊,還未到初始化階段。緩存
在這一章中,我將詳細對 bean 在什麼時候進行實例化、如何放入緩存這部分的內容進行詳細的分析。併發
首先是方法入口,也就是咱們獲取 bean 實例的代碼:app
Student student = defaultListableBeanFactory.getBean("student", Student.class);
複製代碼
咱們深刻到 getBean() 這個方法中:ide
AbstractBeanFactory.getBean()post
能夠發現,這裏調用的是 AbstractBeanFactory 的 getBean() 方法,它是 DefaultListableBeanFactory 的父類。ui
這裏分別 getBean() 方法進行了不一樣的重載,而且底層是調用了 doGetBean() 這個方法:this
//---------------------------------------------------------------------
// Implementation of BeanFactory interface
//---------------------------------------------------------------------
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}
複製代碼
繼續深刻到 doGetBean() :spa
AbstractBeanFactory.doGetBean()prototype
這個方法的代碼很是的多,咱們當下先關注從緩存獲取 bean 實例的邏輯,所以我先省略掉後續的代碼:
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 獲取到bean的惟一標識
final String beanName = transformedBeanName(name);
Object bean;
// 提前地去檢查緩存中是否存在相應的bean實例
// 若是存在就返回相應的單例bean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
//....
}
複製代碼
能夠發現上面這個方法會從單例緩存池中獲取單例bean實例,因而咱們能夠接着深刻:
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
複製代碼
深刻到重載的 getgetSingleton() 方法
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 經過單例bean緩存 singletonObjects 獲取到對應的實例
// 這裏的容器依然是經過 ConcurrentHashMap 來實現的
// key=惟一標識、value=單例bean實例
Object singletonObject = this.singletonObjects.get(beanName);
// 若是發現緩存中不存在對應的bean實例, 而且發現這個bean正處於建立過程當中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 那麼就會進行一個同步
// 避免併發環境下出現的讀寫不一致的問題
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
複製代碼
咱們回到 doGetBean() ,看看後續會進行什麼邏輯:
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 若是緩存池中存在相應的實例, 在這裏就會直接進行返回
// 沒有的話就會返回一個空值
Object sharedInstance = getSingleton(beanName);
// 若是成功從單例緩存池中獲取到了實例
if (sharedInstance != null && args == null) {
// 緊接着去打印一下日誌
if (logger.isTraceEnabled()) {
//....
}
// 將緩存中獲取到的Object轉換爲bean實例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 這裏就是緩存池中不存在實例的邏輯了
else {
// 判斷是不是prototype這種類型的bean正在被建立
// 若是是, 直接拋出異常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 下面這塊邏輯就是檢查 BeanDefinition 是否在工廠中存在
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
//....
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 獲取到 BeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 檢查 bean 的依賴關係
// 好比 A 依賴於 B, 那麼就須要先把 B 建立出來
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
//....
}
// 真正建立 bean 實例的邏輯
if (mbd.isSingleton()) { // 判斷scope是不是singleton
// 這裏經過了 lambda 表達式來處理方法的執行
// 首先會建立一個bean實例, 而後 getSingleton() 方法又會將建立好的 bean 實例緩存到單例緩存池
sharedInstance = getSingleton(beanName, () -> {
try {
// 這裏就會進行一個 bean 實例的建立流程
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 判斷scope是不是prototype
else if (mbd.isPrototype()) {
// ....省略
}
else { // 這邊就是其餘scope類型的bean實例化的邏輯
// ....省略
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// ...省略
return (T) bean;
}
複製代碼
經過上述代碼,咱們可以明確,這個方法中包含了 "建立 bean 實例"、"將實例緩存到單例緩存池中" 這兩個邏輯。
咱們先假設已經成功建立出 bean 實例了,先去看看把實例放入緩存池的代碼 —— getSingleton():
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// ... 省略邏輯咱們不須要太關心, 就是一些前置、後置處理
// 這裏就會獲取到單例bean的對象
// 也就是經過lambda表達式中方法的返回值中獲取到單例bean實例
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
// 關鍵是這裏, 會將惟一標識、單例bean對象放入到緩存中
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
// 最後把這個單例bean實例給返回
return singletonObject;
}
}
複製代碼
咱們深刻一下單例 bean 建立實例,也就是lambda表達式中的代碼:java createBean(beanName, mbd, args);
的執行過程:
AbstractAutowireCapableBeanFactory.createBean()
AbstractAutowireCapableBeanFactory 這個類一樣是 DefaultListableBeanFactory 的父類:
/** * Central method of this class: creates a bean instance, * populates the bean instance, applies post-processors, etc. * @see #doCreateBean */
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
// ... 省略掉其餘的邏輯, 只關心建立實例的邏輯
try {
// 這裏又調用了一個 doCreateBean() 方法
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
複製代碼
咱們繼續深刻到 doCreateBean() 內部的邏輯:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
// ... 省略掉一些代碼
if (instanceWrapper == null) {
// 這裏就是bean真正建立的方法
// 傳入惟一標識、BeanDefinition、參數
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// ... 省略掉一些代碼
return exposedObject;
}
複製代碼
繼續深刻到 createBeanInstance()
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 省略掉其他代碼
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 經過惟一標識、bean定義去實例化bean
return instantiateBean(beanName, mbd);
}
}
// 省略掉其他代碼
}
複製代碼
繼續深刻到 instantiateBean()
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
//...
else {
// 注意這裏的 instantiate 方法, 繼續跟進
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
//...
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
複製代碼
繼續深刻 instantiate()
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
// 獲取到構造方法對象
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// 經過 BeanUtils.instantiateClass() 進行實例化
// 經過反射的方式進行一個實例化
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
複製代碼
經過這篇文章的分析,咱們必需要明確如下幾個關鍵點:
就哪怕我分析的代碼一點都沒看懂也不要緊,這幾個點是必需要明確的。
那麼下一篇,將帶來 Spring Bean 建立策略的一個詳細分析。