Spring核心容器之BeanDefinition解析
前言
現(xiàn)如今,我們一般獲取對(duì)象的方式有兩種,一種是手動(dòng)直接 new;另一種是交給 Spring 管理,Spring 將管理的對(duì)象稱(chēng)之為 Bean,容器會(huì)先實(shí)例化 Bean,然后自動(dòng)注入,實(shí)例化的過(guò)程就需要依賴(lài) BeanDefinition。
BeanDefinition 用于保存 Bean 的相關(guān)信息,包括屬性、構(gòu)造方法參數(shù)、依賴(lài)的 Bean 名稱(chēng)及是否單例、延遲加載等,它是實(shí)例化 Bean 的原材料,Spring 就是根據(jù) BeanDefinition 中的信息實(shí)例化 Bean。
BeanDefinition的繼承體系
BeanDefinition 是一個(gè)接口,它有多個(gè)實(shí)現(xiàn)類(lèi),這些實(shí)現(xiàn)類(lèi)分別描述不同類(lèi)型的 Bean。

BeanDefinition
一個(gè) BeanDefinition 描述了一個(gè) Bean 實(shí)例,實(shí)例包含屬性值、構(gòu)造方法參數(shù)值以及更多實(shí)現(xiàn)信息。該 BeanDefinition 只是是一個(gè)最小的接口,主要目的是允許修改屬性值和其他 Bean 元數(shù)據(jù),這里列出幾個(gè)核心方法。
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
// 單例、原型標(biāo)識(shí)符
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
// 標(biāo)識(shí) Bean 的類(lèi)別,分別對(duì)應(yīng) 用戶定義的 Bean、來(lái)源于配置文件的 Bean、Spring 內(nèi)部的 Bean
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
// 設(shè)置、返回 Bean 的父類(lèi)名稱(chēng)
void setParentName(@Nullable String parentName);
String getParentName();
// 設(shè)置、返回 Bean 的 className
void setBeanClassName(@Nullable String beanClassName);
String getBeanClassName();
// 設(shè)置、返回 Bean 的作用域
void setScope(@Nullable String scope);
String getScope();
// 設(shè)置、返回 Bean 是否懶加載
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
// 設(shè)置、返回當(dāng)前 Bean 所依賴(lài)的其它 Bean 名稱(chēng)。
void setDependsOn(@Nullable String... dependsOn);
String[] getDependsOn();
// 設(shè)置、返回 Bean 是否可以自動(dòng)注入。只對(duì) @Autowired 注解有效
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
// 設(shè)置、返回當(dāng)前 Bean 是否為主要候選 Bean 。
// 當(dāng)同一個(gè)接口有多個(gè)實(shí)現(xiàn)類(lèi)時(shí),通過(guò)該屬性來(lái)配置某個(gè) Bean 為主候選 Bean。
void setPrimary(boolean primary);
boolean isPrimary();
// 設(shè)置、返回創(chuàng)建該 Bean 的工廠類(lèi)。
void setFactoryBeanName(@Nullable String factoryBeanName);
String getFactoryBeanName();
// 設(shè)置、返回創(chuàng)建該 Bean 的工廠方法
void setFactoryMethodName(@Nullable String factoryMethodName);
String getFactoryMethodName();
// 返回該 Bean 構(gòu)造方法參數(shù)值、所有屬性
ConstructorArgumentValues getConstructorArgumentValues();
MutablePropertyValues getPropertyValues();
// 返回該 Bean 是否是單例、是否是非單例、是否是抽象的
boolean isSingleton();
boolean isPrototype();
boolean isAbstract();
// 返回 Bean 的類(lèi)別。類(lèi)別對(duì)應(yīng)上面的三個(gè)屬性值。
int getRole();
...
}
可以看到 BeanDefinition 接口提供了一系列操作 Bean 元數(shù)據(jù)的set、get方法,這些操作為 Bean 的描述定義了一套模板,具體的實(shí)現(xiàn)則交由子類(lèi)。
AnnotatedBeanDefinition
AnnotatedBeanDefinition 是 BeanDefinition 子接口之一,該接口擴(kuò)展了 BeanDefinition 的功能,其用來(lái)操作注解元數(shù)據(jù)。一般情況下,通過(guò)注解方式得到的 Bean(@Component、@Bean),其 BeanDefinition 類(lèi)型都是該接口的實(shí)現(xiàn)類(lèi)。
public interface AnnotatedBeanDefinition extends BeanDefinition {
// 獲得當(dāng)前 Bean 的注解元數(shù)據(jù)
AnnotationMetadata getMetadata();
// 獲得當(dāng)前 Bean 的工廠方法上的元數(shù)據(jù)
MethodMetadata getFactoryMethodMetadata();
}
該接口可以返回兩個(gè)元數(shù)據(jù)的類(lèi):
- AnnotationMetadata:主要對(duì) Bean 的注解信息進(jìn)行操作,如:獲取當(dāng)前 Bean 標(biāo)注的所有注解、判斷是否包含指定注解。
- MethodMetadata:方法的元數(shù)據(jù)類(lèi)。提供獲取方法名稱(chēng)、此方法所屬類(lèi)的全類(lèi)名、是否是抽象方法、判斷是否是靜態(tài)方法、判斷是否是final方法等。
AbstractBeanDefinition
AbstractBeanDefinition 是 BeanDefinition 的子抽象類(lèi),也是其他 BeanDefinition 類(lèi)型的基類(lèi),其實(shí)現(xiàn)了接口中定義的一系列操作方法,并定義了一系列的常量屬性,這些常量會(huì)直接影響到 Spring 實(shí)例化 Bean 時(shí)的策略。核心屬性如下。
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
// 默認(rèn)的 SCOPE,默認(rèn)是單例
public static final String SCOPE_DEFAULT = "";
// 不進(jìn)行自動(dòng)裝配
public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
// 根據(jù) Bean 的名字進(jìn)行自動(dòng)裝配,byName
public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
// 根據(jù) Bean 的類(lèi)型進(jìn)行自動(dòng)裝配,byType
public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
// 根據(jù)構(gòu)造器進(jìn)行自動(dòng)裝配
public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
// 首先嘗試按構(gòu)造器自動(dòng)裝配。如果失敗,再?lài)L試使用 byType 進(jìn)行自動(dòng)裝配。(Spring 3.0 之后已廢除)
public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
// 通過(guò)依賴(lài)檢查來(lái)查看 Bean 的每個(gè)屬性是否都設(shè)置完成
// 以下常量分別對(duì)應(yīng):不檢查、對(duì)依賴(lài)對(duì)象檢查、對(duì)基本類(lèi)型,字符串和集合進(jìn)行檢查、對(duì)全部屬性進(jìn)行檢查
public static final int DEPENDENCY_CHECK_NONE = 0;
public static final int DEPENDENCY_CHECK_OBJECTS = 1;
public static final int DEPENDENCY_CHECK_SIMPLE = 2;
public static final int DEPENDENCY_CHECK_ALL = 3;
// 關(guān)閉應(yīng)用上下文時(shí)需調(diào)用的方法名稱(chēng)
public static final String INFER_METHOD = "(inferred)";
// 存放 Bean 的 Class 對(duì)象
private volatile Object beanClass;
// Bean 的作用范圍
private String scope = SCOPE_DEFAULT;
// 非抽象
private boolean abstractFlag = false;
// 非延遲加載
private boolean lazyInit = false;
// 默認(rèn)不自動(dòng)裝配
private int autowireMode = AUTOWIRE_NO;
// 默認(rèn)不依賴(lài)檢查
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
// 依賴(lài)的 Bean 列表
private String[] dependsOn;
// 可以作為自動(dòng)裝配的候選者,意味著可以自動(dòng)裝配到其他 Bean 的某個(gè)屬性中
private boolean autowireCandidate = true;
// 創(chuàng)建當(dāng)前 Bean 實(shí)例工廠類(lèi)名稱(chēng)
private String factoryBeanName;
// 創(chuàng)建當(dāng)前 Bean 實(shí)例工廠類(lèi)中方法名稱(chēng)
private String factoryMethodName;
// 存儲(chǔ)構(gòu)造方法的參數(shù)
private ConstructorArgumentValues constructorArgumentValues;
// 存儲(chǔ) Bean 屬性名稱(chēng)以及對(duì)應(yīng)的值
private MutablePropertyValues propertyValues;
// 存儲(chǔ)被覆蓋的方法信息
private MethodOverrides methodOverrides;
// init、destroy 方法名稱(chēng)
private String initMethodName;
private String destroyMethodName;
// 是否執(zhí)行 init 和 destroy 方法
private boolean enforceInitMethod = true;
private boolean enforceDestroyMethod = true;
// Bean 是否是用戶定義的而不是應(yīng)用程序本身定義的
private boolean synthetic = false;
// Bean 的身份類(lèi)別,默認(rèn)是用戶定義的 Bean
private int role = BeanDefinition.ROLE_APPLICATION;
// Bean 的描述信息
private String description;
// Bean 定義的資源
private Resource resource;
...
}以上是 AbstractBeanDefinition 中定義的一些常量和屬性,該類(lèi)中還有一部分是操作這些屬性的 set 和 get 方法,這些方法都由子類(lèi)來(lái)操作,且應(yīng)用程序中真正使用的也是這些子類(lèi) BeanDefinition。
先來(lái)看 AbstractBeanDefinition 直接實(shí)現(xiàn)類(lèi):RootBeanDefinition、GenericBeanDefinition、ChildBeanDefinition。
RootBeanDefinition
該類(lèi)繼承自 AbstractBeanDefinition,它可以單獨(dú)作為一個(gè) BeanDefinition,也可以作為其他 BeanDefinition 的父類(lèi)。
RootBeanDefinition 在 AbstractBeanDefinition 的基礎(chǔ)上定義了更多屬性。
public class RootBeanDefinition extends AbstractBeanDefinition {
// BeanDefinitionHolder 存儲(chǔ) Bean 的名稱(chēng)、別名、BeanDefinition
private BeanDefinitionHolder decoratedDefinition;
// AnnotatedElement 是java反射包的接口,通過(guò)它可以查看 Bean 的注解信息
private AnnotatedElement qualifiedElement;
// 允許緩存
boolean allowCaching = true;
// 工廠方法是否唯一
boolean isFactoryMethodUnique = false;
// 封裝了 java.lang.reflect.Type,提供了泛型相關(guān)的操作
volatile ResolvableType targetType;
// 緩存 Class,表示 RootBeanDefinition 存儲(chǔ)哪個(gè)類(lèi)的信息
volatile Class<?> resolvedTargetType;
// 緩存工廠方法的返回類(lèi)型
volatile ResolvableType factoryMethodReturnType;
// 這是以下四個(gè)構(gòu)造方法字段的通用鎖
final Object constructorArgumentLock = new Object();
// 用于緩存已解析的構(gòu)造方法或工廠方法
Executable resolvedConstructorOrFactoryMethod;
// 將構(gòu)造方法參數(shù)標(biāo)記為已解析
boolean constructorArgumentsResolved = false;
// 用于緩存完全解析的構(gòu)造方法參數(shù)
Object[] resolvedConstructorArguments;
// 緩存待解析的構(gòu)造方法參數(shù)
Object[] preparedConstructorArguments;
// 這是以下兩個(gè)后處理字段的通用鎖
final Object postProcessingLock = new Object();
// 表明是否被 MergedBeanDefinitionPostProcessor 處理過(guò)
boolean postProcessed = false;
// 在生成代理的時(shí)候會(huì)使用,表明是否已經(jīng)生成代理
volatile Boolean beforeInstantiationResolved;
// 實(shí)際緩存的類(lèi)型是 Constructor、Field、Method 類(lèi)型
private Set<Member> externallyManagedConfigMembers;
// InitializingBean中 的 init 回調(diào)函數(shù)名 afterPropertiesSet 會(huì)在這里記錄,以便進(jìn)行生命周期回調(diào)
private Set<String> externallyManagedInitMethods;
// DisposableBean 的 destroy 回調(diào)函數(shù)名 destroy 會(huì)在這里記錄,以便進(jìn)生命周期回調(diào)
private Set<String> externallyManagedDestroyMethods;
...
}
ChildBeanDefinition
該類(lèi)繼承自 AbstractBeanDefinition。其相當(dāng)于一個(gè)子類(lèi),不可以單獨(dú)存在,必須依賴(lài)一個(gè)父 BeanDetintion,構(gòu)造 ChildBeanDefinition 時(shí),通過(guò)構(gòu)造方法傳入父 BeanDetintion 的名稱(chēng)或通過(guò) setParentName 設(shè)置父名稱(chēng)。它可以從父類(lèi)繼承方法參數(shù)、屬性值,并可以重寫(xiě)父類(lèi)的方法,同時(shí)也可以增加新的屬性或者方法。若重新定義 init 方法,destroy 方法或者靜態(tài)工廠方法,ChildBeanDefinition 會(huì)重寫(xiě)父類(lèi)的設(shè)置。
從 Spring 2.5 開(kāi)始,以編程方式注冊(cè) Bean 定義的首選方法是 GenericBeanDefinition,GenericBeanDefinition 可以有效替代 ChildBeanDefinition 的絕大分部使用場(chǎng)合。
GenericBeanDefinition
GenericBeanDefinition 是 Spring 2.5 以后新引入的 BeanDefinition,是 ChildBeanDefinition 更好的替代者,它同樣可以通過(guò) setParentName 方法設(shè)置父 BeanDefinition。
最后三個(gè) BeanDefinition 既實(shí)現(xiàn)了 AnnotatedBeanDefinition 接口,又間接繼承 AbstractBeanDefinition 抽象類(lèi),這些 BeanDefinition 描述的都是注解形式的 Bean。
ConfigurationClassBeanDefinition
該類(lèi)繼承自 RootBeanDefinition ,并實(shí)現(xiàn)了 AnnotatedBeanDefinition 接口。這個(gè) BeanDefinition 用來(lái)描述在標(biāo)注 @Configuration 注解的類(lèi)中,通過(guò) @Bean 注解實(shí)例化的 Bean。
其功能特點(diǎn)如下:
1、如果 @Bean 注解沒(méi)有指定 Bean 的名字,默認(rèn)會(huì)用方法的名字命名 Bean。
2、標(biāo)注 @Configuration 注解的類(lèi)會(huì)成為一個(gè)工廠類(lèi),而標(biāo)注 @Bean 注解的方法會(huì)成為工廠方法,通過(guò)工廠方法實(shí)例化 Bean,而不是直接通過(guò)構(gòu)造方法初始化。
3、標(biāo)注 @Bean 注解的類(lèi)會(huì)使用構(gòu)造方法自動(dòng)裝配
AnnotatedGenericBeanDefinition
該類(lèi)繼承自 GenericBeanDefinition ,并實(shí)現(xiàn)了 AnnotatedBeanDefinition 接口。這個(gè) BeanDefinition 用來(lái)描述標(biāo)注 @Configuration 注解的 Bean。
ScannedGenericBeanDefinition
該類(lèi)繼承自 GenericBeanDefinition ,并實(shí)現(xiàn)了 AnnotatedBeanDefinition 接口。這個(gè) BeanDefinition 用來(lái)描述標(biāo)注 @Component 注解的 Bean,其派生注解如 @Service、@Controller 也同理。
總結(jié)
最后,我們來(lái)做個(gè)總結(jié)。BeanDefinition 主要是用來(lái)描述 Bean,其存儲(chǔ)了 Bean 的相關(guān)信息,Spring 實(shí)例化 Bean 時(shí)需讀取該 Bean 對(duì)應(yīng)的 BeanDefinition。
BeanDefinition 整體可以分為兩類(lèi),一類(lèi)是描述通用的 Bean,還有一類(lèi)是描述注解形式的 Bean。
一般前者在 XML 時(shí)期定義 <bean’> 標(biāo)簽以及在 Spring 內(nèi)部使用較多,而現(xiàn)今我們大都使用后者,通過(guò)注解形式加載 Bean。
到此這篇關(guān)于Spring核心容器之BeanDefinition解析的文章就介紹到這了,更多相關(guān)Spring的BeanDefinition解析內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于Java實(shí)現(xiàn)PPT到PDF的高效轉(zhuǎn)換詳解
在日常開(kāi)發(fā)中,經(jīng)常會(huì)遇到將PPT文檔批量或單文件轉(zhuǎn)換為PDF的需求,本文將詳細(xì)介紹其使用流程、核心代碼與常見(jiàn)問(wèn)題解決方案,希望對(duì)大家有所幫助2025-11-11
深入學(xué)習(xí)JAVA GC日志的相關(guān)知識(shí)
JVM 在Java應(yīng)用程序優(yōu)化中是不可缺少的一大重項(xiàng),如何合理配置Java參數(shù),如何驗(yàn)證配置參數(shù)的有效性,從GC日志中可以獲得很重要的提示。下面小編就帶大家來(lái)一起學(xué)習(xí)一下吧2019-06-06
java獲取當(dāng)前時(shí)間和前一天日期(實(shí)現(xiàn)代碼)
java獲取當(dāng)前時(shí)間和前一天日期的實(shí)現(xiàn)代碼。需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-10-10
如何利用SpringBoot搭建WebService服務(wù)接口
之前項(xiàng)目經(jīng)理想要開(kāi)發(fā)一個(gè)webservice的協(xié)議,給我一個(gè)星期的時(shí)間,后面用springboot開(kāi)發(fā)了webservice,這篇文章主要給大家介紹了關(guān)于如何利用SpringBoot搭建WebService服務(wù)接口的相關(guān)資料,需要的朋友可以參考下2023-11-11
Spring如何使用@Indexed加快啟動(dòng)速度
這篇文章主要介紹了Spring如何使用@Indexed加快啟動(dòng)速度,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
@TableName注解和@Table的區(qū)別及說(shuō)明
這篇文章主要介紹了@TableName注解和@Table的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01

