欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring核心容器之BeanDefinition解析

 更新時間:2023年11月16日 11:11:30   作者:龍三丶  
這篇文章主要介紹了Spring核心容器之BeanDefinition解析,Spring 將管理的對象稱之為 Bean,容器會先實例化 Bean,然后自動注入,實例化的過程就需要依賴 BeanDefinition,需要的朋友可以參考下

前言

現(xiàn)如今,我們一般獲取對象的方式有兩種,一種是手動直接 new;另一種是交給 Spring 管理,Spring 將管理的對象稱之為 Bean,容器會先實例化 Bean,然后自動注入,實例化的過程就需要依賴 BeanDefinition。

BeanDefinition 用于保存 Bean 的相關(guān)信息,包括屬性、構(gòu)造方法參數(shù)、依賴的 Bean 名稱及是否單例、延遲加載等,它是實例化 Bean 的原材料,Spring 就是根據(jù) BeanDefinition 中的信息實例化 Bean。

BeanDefinition的繼承體系

BeanDefinition 是一個接口,它有多個實現(xiàn)類,這些實現(xiàn)類分別描述不同類型的 Bean。

image

BeanDefinition

一個 BeanDefinition 描述了一個 Bean 實例,實例包含屬性值、構(gòu)造方法參數(shù)值以及更多實現(xiàn)信息。該 BeanDefinition 只是是一個最小的接口,主要目的是允許修改屬性值和其他 Bean 元數(shù)據(jù),這里列出幾個核心方法。

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	// 單例、原型標(biāo)識符
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

    // 標(biāo)識 Bean 的類別,分別對應(yīng) 用戶定義的 Bean、來源于配置文件的 Bean、Spring 內(nèi)部的 Bean
	int ROLE_APPLICATION = 0;
	int ROLE_SUPPORT = 1;
	int ROLE_INFRASTRUCTURE = 2;

    // 設(shè)置、返回 Bean 的父類名稱
	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 所依賴的其它 Bean 名稱。
	void setDependsOn(@Nullable String... dependsOn);
	String[] getDependsOn();
	
	// 設(shè)置、返回 Bean 是否可以自動注入。只對 @Autowired 注解有效
	void setAutowireCandidate(boolean autowireCandidate);
	boolean isAutowireCandidate();
	
	// 設(shè)置、返回當(dāng)前 Bean 是否為主要候選 Bean 。
	// 當(dāng)同一個接口有多個實現(xiàn)類時,通過該屬性來配置某個 Bean 為主候選 Bean。
	void setPrimary(boolean primary);
	boolean isPrimary();

    // 設(shè)置、返回創(chuàng)建該 Bean 的工廠類。
	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 的類別。類別對應(yīng)上面的三個屬性值。
	int getRole();

    ...
}

可以看到 BeanDefinition 接口提供了一系列操作 Bean 元數(shù)據(jù)的set、get方法,這些操作為 Bean 的描述定義了一套模板,具體的實現(xiàn)則交由子類。

AnnotatedBeanDefinition

AnnotatedBeanDefinition 是 BeanDefinition 子接口之一,該接口擴展了 BeanDefinition 的功能,其用來操作注解元數(shù)據(jù)。一般情況下,通過注解方式得到的 Bean(@Component、@Bean),其 BeanDefinition 類型都是該接口的實現(xiàn)類。

public interface AnnotatedBeanDefinition extends BeanDefinition {

	// 獲得當(dāng)前 Bean 的注解元數(shù)據(jù)
	AnnotationMetadata getMetadata();

	// 獲得當(dāng)前 Bean 的工廠方法上的元數(shù)據(jù)
	MethodMetadata getFactoryMethodMetadata();
}

該接口可以返回兩個元數(shù)據(jù)的類:

  • AnnotationMetadata:主要對 Bean 的注解信息進(jìn)行操作,如:獲取當(dāng)前 Bean 標(biāo)注的所有注解、判斷是否包含指定注解。
  • MethodMetadata:方法的元數(shù)據(jù)類。提供獲取方法名稱、此方法所屬類的全類名、是否是抽象方法、判斷是否是靜態(tài)方法、判斷是否是final方法等。

AbstractBeanDefinition

AbstractBeanDefinition 是 BeanDefinition 的子抽象類,也是其他 BeanDefinition 類型的基類,其實現(xiàn)了接口中定義的一系列操作方法,并定義了一系列的常量屬性,這些常量會直接影響到 Spring 實例化 Bean 時的策略。核心屬性如下。

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
		implements BeanDefinition, Cloneable {
    // 默認(rèn)的 SCOPE,默認(rèn)是單例
	public static final String SCOPE_DEFAULT = "";
	// 不進(jìn)行自動裝配
	public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
    // 根據(jù) Bean 的名字進(jìn)行自動裝配,byName
	public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
	// 根據(jù) Bean 的類型進(jìn)行自動裝配,byType
	public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
	// 根據(jù)構(gòu)造器進(jìn)行自動裝配
	public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
	// 首先嘗試按構(gòu)造器自動裝配。如果失敗,再嘗試使用 byType 進(jìn)行自動裝配。(Spring 3.0 之后已廢除)
	public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
    // 通過依賴檢查來查看 Bean 的每個屬性是否都設(shè)置完成
    // 以下常量分別對應(yīng):不檢查、對依賴對象檢查、對基本類型,字符串和集合進(jìn)行檢查、對全部屬性進(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)用上下文時需調(diào)用的方法名稱
	public static final String INFER_METHOD = "(inferred)";
    // 存放 Bean 的 Class 對象
	private volatile Object beanClass;
	// Bean 的作用范圍
	private String scope = SCOPE_DEFAULT;
    // 非抽象
	private boolean abstractFlag = false;
	// 非延遲加載
	private boolean lazyInit = false;
    // 默認(rèn)不自動裝配
	private int autowireMode = AUTOWIRE_NO;
    // 默認(rèn)不依賴檢查
	private int dependencyCheck = DEPENDENCY_CHECK_NONE;
	// 依賴的 Bean 列表
	private String[] dependsOn;
    // 可以作為自動裝配的候選者,意味著可以自動裝配到其他 Bean 的某個屬性中
	private boolean autowireCandidate = true;
	// 創(chuàng)建當(dāng)前 Bean 實例工廠類名稱
	private String factoryBeanName;
    // 創(chuàng)建當(dāng)前 Bean 實例工廠類中方法名稱
	private String factoryMethodName;
	// 存儲構(gòu)造方法的參數(shù)
	private ConstructorArgumentValues constructorArgumentValues;
    // 存儲 Bean 屬性名稱以及對應(yīng)的值
	private MutablePropertyValues propertyValues;
    // 存儲被覆蓋的方法信息
	private MethodOverrides methodOverrides;
	// init、destroy 方法名稱
	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 的身份類別,默認(rèn)是用戶定義的 Bean
	private int role = BeanDefinition.ROLE_APPLICATION;
	// Bean 的描述信息
	private String description;
	// Bean 定義的資源
	private Resource resource;
	...
}

以上是 AbstractBeanDefinition 中定義的一些常量和屬性,該類中還有一部分是操作這些屬性的 set 和 get 方法,這些方法都由子類來操作,且應(yīng)用程序中真正使用的也是這些子類 BeanDefinition。

先來看 AbstractBeanDefinition 直接實現(xiàn)類:RootBeanDefinition、GenericBeanDefinition、ChildBeanDefinition。

RootBeanDefinition

該類繼承自 AbstractBeanDefinition,它可以單獨作為一個 BeanDefinition,也可以作為其他 BeanDefinition 的父類。

RootBeanDefinition 在 AbstractBeanDefinition 的基礎(chǔ)上定義了更多屬性。

public class RootBeanDefinition extends AbstractBeanDefinition {

    // BeanDefinitionHolder 存儲 Bean 的名稱、別名、BeanDefinition
	private BeanDefinitionHolder decoratedDefinition;

	// AnnotatedElement 是java反射包的接口,通過它可以查看 Bean 的注解信息
	private AnnotatedElement qualifiedElement;

    // 允許緩存
	boolean allowCaching = true;
    
    // 工廠方法是否唯一
	boolean isFactoryMethodUnique = false;

	// 封裝了 java.lang.reflect.Type,提供了泛型相關(guān)的操作
	volatile ResolvableType targetType;

	// 緩存 Class,表示 RootBeanDefinition 存儲哪個類的信息
	volatile Class<?> resolvedTargetType;

	// 緩存工廠方法的返回類型
	volatile ResolvableType factoryMethodReturnType;

	// 這是以下四個構(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;

	// 這是以下兩個后處理字段的通用鎖
	final Object postProcessingLock = new Object();
	// 表明是否被 MergedBeanDefinitionPostProcessor 處理過
	boolean postProcessed = false;
	// 在生成代理的時候會使用,表明是否已經(jīng)生成代理
	volatile Boolean beforeInstantiationResolved;

	// 實際緩存的類型是 Constructor、Field、Method 類型
	private Set<Member> externallyManagedConfigMembers;

	// InitializingBean中 的 init 回調(diào)函數(shù)名 afterPropertiesSet 會在這里記錄,以便進(jìn)行生命周期回調(diào)
	private Set<String> externallyManagedInitMethods;

	// DisposableBean 的 destroy 回調(diào)函數(shù)名 destroy 會在這里記錄,以便進(jìn)生命周期回調(diào)
	private Set<String> externallyManagedDestroyMethods;

    ...
}

ChildBeanDefinition

該類繼承自 AbstractBeanDefinition。其相當(dāng)于一個子類,不可以單獨存在,必須依賴一個父 BeanDetintion,構(gòu)造 ChildBeanDefinition 時,通過構(gòu)造方法傳入父 BeanDetintion 的名稱或通過 setParentName 設(shè)置父名稱。它可以從父類繼承方法參數(shù)、屬性值,并可以重寫父類的方法,同時也可以增加新的屬性或者方法。若重新定義 init 方法,destroy 方法或者靜態(tài)工廠方法,ChildBeanDefinition 會重寫父類的設(shè)置。

從 Spring 2.5 開始,以編程方式注冊 Bean 定義的首選方法是 GenericBeanDefinition,GenericBeanDefinition 可以有效替代 ChildBeanDefinition 的絕大分部使用場合。

GenericBeanDefinition

GenericBeanDefinition 是 Spring 2.5 以后新引入的 BeanDefinition,是 ChildBeanDefinition 更好的替代者,它同樣可以通過 setParentName 方法設(shè)置父 BeanDefinition。

最后三個 BeanDefinition 既實現(xiàn)了 AnnotatedBeanDefinition 接口,又間接繼承 AbstractBeanDefinition 抽象類,這些 BeanDefinition 描述的都是注解形式的 Bean。

ConfigurationClassBeanDefinition

該類繼承自 RootBeanDefinition ,并實現(xiàn)了 AnnotatedBeanDefinition 接口。這個 BeanDefinition 用來描述在標(biāo)注 @Configuration 注解的類中,通過 @Bean 注解實例化的 Bean。

其功能特點如下:

1、如果 @Bean 注解沒有指定 Bean 的名字,默認(rèn)會用方法的名字命名 Bean。

2、標(biāo)注 @Configuration 注解的類會成為一個工廠類,而標(biāo)注 @Bean 注解的方法會成為工廠方法,通過工廠方法實例化 Bean,而不是直接通過構(gòu)造方法初始化。

3、標(biāo)注 @Bean 注解的類會使用構(gòu)造方法自動裝配

AnnotatedGenericBeanDefinition

該類繼承自 GenericBeanDefinition ,并實現(xiàn)了 AnnotatedBeanDefinition 接口。這個 BeanDefinition 用來描述標(biāo)注 @Configuration 注解的 Bean。

ScannedGenericBeanDefinition

該類繼承自 GenericBeanDefinition ,并實現(xiàn)了 AnnotatedBeanDefinition 接口。這個 BeanDefinition 用來描述標(biāo)注 @Component 注解的 Bean,其派生注解如 @Service、@Controller 也同理。

總結(jié)

最后,我們來做個總結(jié)。BeanDefinition 主要是用來描述 Bean,其存儲了 Bean 的相關(guān)信息,Spring 實例化 Bean 時需讀取該 Bean 對應(yīng)的 BeanDefinition。

BeanDefinition 整體可以分為兩類,一類是描述通用的 Bean,還有一類是描述注解形式的 Bean。

一般前者在 XML 時期定義 <bean’> 標(biāo)簽以及在 Spring 內(nèi)部使用較多,而現(xiàn)今我們大都使用后者,通過注解形式加載 Bean。

到此這篇關(guān)于Spring核心容器之BeanDefinition解析的文章就介紹到這了,更多相關(guān)Spring的BeanDefinition解析內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java實現(xiàn)相同屬性名稱及相似類型的pojo、dto、vo等互轉(zhuǎn)操作

    java實現(xiàn)相同屬性名稱及相似類型的pojo、dto、vo等互轉(zhuǎn)操作

    這篇文章主要介紹了java實現(xiàn)相同屬性名稱及相似類型的pojo、dto、vo等互轉(zhuǎn)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • SpringBoot下使用MyBatis-Puls代碼生成器的方法

    SpringBoot下使用MyBatis-Puls代碼生成器的方法

    這篇文章主要介紹了SpringBoot下使用MyBatis-Puls代碼生成器的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • 詳解Java項目中讀取properties文件

    詳解Java項目中讀取properties文件

    本篇文章主要介紹了Java項目中讀取properties文件,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2016-12-12
  • Java BigDecimal解決double精度丟失的問題

    Java BigDecimal解決double精度丟失的問題

    我們在日常開發(fā)中, 有很多時候會遇到小數(shù)(double類型)精確計算,本文主要介紹了Java BigDecimal解決double精度丟失的問題,具有一定的參考價值,感興趣的可以了解一下
    2023-11-11
  • Java+mysql用戶注冊登錄功能

    Java+mysql用戶注冊登錄功能

    這篇文章主要為大家詳細(xì)介紹了Java結(jié)合mysql實現(xiàn)用戶注冊登錄功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Java基于final修飾數(shù)據(jù)過程解析

    Java基于final修飾數(shù)據(jù)過程解析

    這篇文章主要介紹了Java基于final修飾數(shù)據(jù)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • 解決SpringMVC @RequestMapping不設(shè)置value出現(xiàn)的問題

    解決SpringMVC @RequestMapping不設(shè)置value出現(xiàn)的問題

    這篇文章主要介紹了解決SpringMVC @RequestMapping不設(shè)置value出現(xiàn)的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java基于棧方式解決漢諾塔問題實例【遞歸與非遞歸算法】

    Java基于棧方式解決漢諾塔問題實例【遞歸與非遞歸算法】

    這篇文章主要介紹了Java基于棧方式解決漢諾塔問題的方法,結(jié)合實例形式分析了java棧方式采用遞歸與非遞歸算法解決漢諾塔問題的相關(guān)操作技巧,需要的朋友可以參考下
    2017-11-11
  • java實現(xiàn)根據(jù)ip地址獲取地理位置

    java實現(xiàn)根據(jù)ip地址獲取地理位置

    本文給大家匯總介紹了2種分別使用新浪和淘寶接口,實現(xiàn)根據(jù)IP地址獲取詳細(xì)的地理位置的代碼,非常的實用,有需要的小伙伴可以參考下。
    2016-03-03
  • Spring中的依賴注入DI詳解

    Spring中的依賴注入DI詳解

    這篇文章主要介紹了Spring中的依賴注入DI詳解,組件之間依賴關(guān)系由容器在運行期決定,形象的說,即由容器動態(tài)的將依賴關(guān)系注入到組件之中,依賴注入的目的并非為軟件系統(tǒng)帶來更多功能,是為了提升組件重用的頻率,并為系統(tǒng)搭建一個靈活、可擴展的平臺,需要的朋友可以參考下
    2024-01-01

最新評論