該系列文章是本人在學習 Spring 的過程當中總結下來的,裏面涉及到相關源碼,可能對讀者不太友好,請結合個人源碼註釋 Spring 源碼分析 GitHub 地址 進行閱讀html
Spring 版本:5.1.14.RELEASEjava
開始閱讀這一系列文章以前,建議先查看《深刻了解 Spring IoC(面試題)》這一篇文章git
該系列其餘文章請查看:《死磕 Spring 之 IoC 篇 - 文章導讀》github
咱們在 Spring 中一般以這兩種方式定義一個 Bean:面向資源(XML、Properties)、面向註解。現在 Spring Boot 被普遍應用,經過註解定義一個 Bean 的方式變得更爲廣泛,由於在實際的開發過程當中註解的方式相比於 XML 文件更加輕便,能夠有效地提升工做效率。你是否這瞭解這兩種方式在 Spring 內是如何進行處理的,將咱們的配置信息轉換成 Spring Bean,並管理着這些它們的生命週期面試
在 Spring Bean 的生命週期 能夠看到,BeanDefinition 能夠說是 Bean 的「前身」,首先進入 Bean 的元信息的配置、解析和註冊階段,而後纔開始 Bean 的實例化和初始化等工做。接下來,咱們就一塊兒來看看 Bean 的「前身」是什麼spring
BeanDefinition 是 Spring Framework 中定義 Bean 的配置元信息接口,主要包含一下信息:框架
org.springframework.beans.factory.config.BeanDefinition
接口的類圖以下所示:ide
總覽:源碼分析
org.springframework.core.AttributeAccessor
接口,用於獲取元數據,在實現類中經過 LinkedHashMap 集合保存元數據,例如經過 XML 的 <meta />
標籤訂義的一些元信息會保存在其中學習
org.springframework.beans.BeanMetadataElement
接口,用於獲取定義 Bean 的源對象,在實現類中經過 Object 對象保存,所謂的源對象就是定義這個 Bean 的資源(XML 標籤對象或者 .class 文件資源對象)
org.springframework.beans.factory.config.BeanDefinition
接口,定義一個 Bean 的元信息
org.springframework.beans.factory.support.AbstractBeanDefinition
抽象類,實現 BeanDefinition 接口,包含了一個 Bean 幾乎全部的元信息
org.springframework.beans.factory.support.GenericBeanDefinition
,繼承 AbstractBeanDefinition 抽象類,多了一個 parentName
,表示有繼承關係,是一個標準 Bean 元信息對象,經過 XML 定義的 Bean 會解析成該對象
org.springframework.beans.factory.annotation.AnnotatedBeanDefinition
接口,繼承 BeanDefinition 接口,定義註解類的元信息,例如經過 @Component
註解定義的 Bean,那麼註解類的元信息會包含編譯後的 .class 文件的全部信息
org.springframework.context.annotation.ScannedGenericBeanDefinition
,繼承 GenericBeanDefinition,實現 AnnotatedBeanDefinition 接口,多了一個 AnnotationMetadata 註解類元信息對象,例如經過 @Component
註解定義的 Bean 會解析成該對象
org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition
,繼承 GenericBeanDefinition,實現 AnnotatedBeanDefinition 接口,和 ScannedGenericBeanDefinition 相似,經過 @Import
導入的 Configuration Class
會解析成該對象
org.springframework.beans.factory.support.RootBeanDefinition
,繼承 AbstractBeanDefinition 抽象類,表示合併後的 BeanDefinition 對象。在 Spring BeanFactory 初始化 Bean 的前階段,會根據 BeanDefinition 生成一個 RootBeanDefinition(具備層次性則會進行合併),用於後續實例化和初始化
org.springframework.context.annotation.ConfigurationClassBeanDefinition$ConfigurationClassBeanDefinition
私有靜態類,繼承 RootBeanDefinition,實現了 AnnotatedBeanDefinition 接口,和 AnnotatedGenericBeanDefinition 相似,沒有繼承關係,經過 @Bean
定義的方法會解析成該對象
org.springframework.beans.factory.config.BeanDefinitionHolder
,包含 BeanDefinition、Bean 的名稱以及別名(支持多個)總結一下,BeanDefinition 接口的實現類主要根據 Bean 的定義方式進行區分,以下:
XML 定義 Bean >>>>> GenericBeanDefinition
@Component 以及派生註解定義 Bean >>>>> ScannedGenericBeanDefinition
藉助於 @Import 導入 Bean >>>>> AnnotatedGenericBeanDefinition
@Bean 定義的方法 >>>>> ConfigurationClassBeanDefinition
在 Spring BeanFactory 初始化 Bean 的前階段,會根據 BeanDefinition 生成一個合併後的 RootBeanDefinition 對象
org.springframework.beans.factory.config.BeanDefinition
接口,繼承 AttributeAccessor 和 BeanMetadataElement 兩個接口,定義一個 Bean 的元信息
BeanDefinition 內部就定義了獲取一些基礎元信息的方法,可跳轉 BeanDefinition.java 查看
org.springframework.beans.factory.support.AbstractBeanDefinition
抽象類,實現 BeanDefinition 接口,繼承 BeanMetadataAttributeAccessor 類(AttributeAccessor 和 BeanMetadataElement 的實現類),包含了一個 Bean 幾乎全部的元信息,可跳轉 AbstractBeanDefinition.java 查看,下面列舉最多見的屬性:
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable { @Nullable private volatile Object beanClass; private boolean abstractFlag = false; private boolean lazyInit = false; @Nullable private String[] dependsOn; private boolean primary = false; private boolean nonPublicAccessAllowed = true; @Nullable private String factoryBeanName; @Nullable private String factoryMethodName; @Nullable private ConstructorArgumentValues constructorArgumentValues; @Nullable private MutablePropertyValues propertyValues; @Nullable private String initMethodName; @Nullable private String destroyMethodName; private boolean enforceInitMethod = true; private boolean enforceDestroyMethod = true; private boolean synthetic = false; private int role = BeanDefinition.ROLE_APPLICATION; @Nullable private String description; @Nullable private Resource resource; // ... 省略大量代碼 }
org.springframework.beans.factory.support.GenericBeanDefinition
,繼承 AbstractBeanDefinition 抽象類,多了一個 parentName
,表示有繼承關係,是一個標準 Bean 元信息對象,經過 XML 定義的 Bean 會解析成該對象,代碼以下:
public class GenericBeanDefinition extends AbstractBeanDefinition { @Nullable private String parentName; public GenericBeanDefinition() { super(); } public GenericBeanDefinition(BeanDefinition original) { super(original); } // ... 省略相關方法 }
org.springframework.beans.factory.annotation.AnnotatedBeanDefinition
接口,繼承 BeanDefinition 接口,定義註解類的元信息,代碼以下:
public interface AnnotatedBeanDefinition extends BeanDefinition { /** * Obtain the annotation metadata (as well as basic class metadata) * for this bean definition's bean class. * @return the annotation metadata object (never {@code null}) */ AnnotationMetadata getMetadata(); /** * Obtain metadata for this bean definition's factory method, if any. * @return the factory method metadata, or {@code null} if none * @since 4.1.1 */ @Nullable MethodMetadata getFactoryMethodMetadata(); }
AnnotationMetadata 能夠獲取到定義 Bean 的全部信息,在 Spring 底層會經過 ASM(一個操做 Java 字節碼與分析的框架)實現的
MethodMetadata 能夠獲取到工廠方法的元信息,目前我沒發現哪裏使用到
例如經過 @Component
註解定義的 Bean,那麼 AnnotationMetadata 能夠獲取到這個 Class 對象的全部信息
org.springframework.context.annotation.ScannedGenericBeanDefinition
,繼承 GenericBeanDefinition,實現 AnnotatedBeanDefinition 接口,多了一個 AnnotationMetadata 註解類元信息對象,例如經過 @Component
註解定義的 Bean 會解析成該對象,代碼以下:
public class ScannedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition { private final AnnotationMetadata metadata; public ScannedGenericBeanDefinition(MetadataReader metadataReader) { Assert.notNull(metadataReader, "MetadataReader must not be null"); this.metadata = metadataReader.getAnnotationMetadata(); setBeanClassName(this.metadata.getClassName()); } @Override public final AnnotationMetadata getMetadata() { return this.metadata; } @Override @Nullable public MethodMetadata getFactoryMethodMetadata() { return null; } }
org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition
,繼承 GenericBeanDefinition,實現 AnnotatedBeanDefinition 接口,和 ScannedGenericBeanDefinition 相似,代碼以下:
public class AnnotatedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition { private final AnnotationMetadata metadata; @Nullable private MethodMetadata factoryMethodMetadata; public AnnotatedGenericBeanDefinition(Class<?> beanClass) { setBeanClass(beanClass); this.metadata = new StandardAnnotationMetadata(beanClass, true); } public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata) { Assert.notNull(metadata, "AnnotationMetadata must not be null"); if (metadata instanceof StandardAnnotationMetadata) { setBeanClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass()); } else { setBeanClassName(metadata.getClassName()); } this.metadata = metadata; } public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata, MethodMetadata factoryMethodMetadata) { this(metadata); Assert.notNull(factoryMethodMetadata, "MethodMetadata must not be null"); setFactoryMethodName(factoryMethodMetadata.getMethodName()); this.factoryMethodMetadata = factoryMethodMetadata; } @Override public final AnnotationMetadata getMetadata() { return this.metadata; } @Override @Nullable public final MethodMetadata getFactoryMethodMetadata() { return this.factoryMethodMetadata; } }
經過 @Import
導入的 Configuration Class
會解析成該對象,不過 factoryMethodMetadata
仍是爲 null
org.springframework.beans.factory.support.RootBeanDefinition
,繼承 AbstractBeanDefinition 抽象類,表示合併後的 BeanDefinition 對象
在 Spring BeanFactory 初始化 Bean 的前階段,會根據 BeanDefinition 生成一個 RootBeanDefinition(具備層次性則會進行合併),用於後續實例化和初始化
可跳轉 RootBeanDefinition.java 查看
org.springframework.beans.factory.config.BeanDefinitionHolder
,包含 BeanDefinition、Bean 的名稱以及別名(支持多個),代碼以下:
public class BeanDefinitionHolder implements BeanMetadataElement { private final BeanDefinition beanDefinition; private final String beanName; @Nullable private final String[] aliases; public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName) { this(beanDefinition, beanName, null); } public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName, @Nullable String[] aliases) { Assert.notNull(beanDefinition, "BeanDefinition must not be null"); Assert.notNull(beanName, "Bean name must not be null"); this.beanDefinition = beanDefinition; this.beanName = beanName; this.aliases = aliases; } }
在解析出來 BeanDefinition 後都會轉換成 BeanDefinitionHolder 對象,而後進行註冊
Spring Bean 的「前身」爲 BeanDefinition 對象,裏面包含了 Bean 的元信息,後續在 Bean 的生命週期中會根據該對象進行實例化和初始化等工做
BeanDefinition 接口的實現類主要根據 Bean 的定義方式進行區分,以下:
XML 定義 Bean:GenericBeanDefinition
@Component 以及派生註解定義 Bean:ScannedGenericBeanDefinition
藉助於 @Import 導入 Bean:AnnotatedGenericBeanDefinition
@Bean 定義的方法:ConfigurationClassBeanDefinition 私有靜態類
上面的 1
、2
、3
三種 BeanDefinition 實現類具備層次性,在 Spring BeanFactory 初始化 Bean 的前階段,會根據 BeanDefinition 生成一個合併後的 RootBeanDefinition 對象