Spring BeanDefinition使用介紹
1. 前言
Spring最重要的一個(gè)概念當(dāng)屬Bean了,我們寫的Controller、Service、Dao凡是加了對(duì)應(yīng)注解交給Spring管理的,都是Spring容器中的一個(gè)Bean。把我們自己寫的類變成一個(gè)Bean交給Spring管理有很多的好處,比如我們不用自己去new對(duì)象了,Spring會(huì)幫我們?cè)谶m當(dāng)?shù)臅r(shí)候去實(shí)例化對(duì)象;再比如Spring還會(huì)維護(hù)Bean的依賴關(guān)系,自動(dòng)注入依賴的對(duì)象;再比如Spring還可以基于Bean生成代理對(duì)象,來對(duì)原生的Bean進(jìn)行功能上的增強(qiáng)等等。
在Spring源碼中,有一個(gè)重要的接口BeanDefinition,它用來表示Bean的定義。比如Bean的名稱、所屬的Class、是否需要延遲實(shí)例化,是單例還是原型?等等信息。不管你是通過xml來配置,還是JavaConfig的方式,還是基于注解的方式,在Spring看來它們都是一個(gè)BeanDefinition。
2. BeanDefinition
BeanDefinition是一個(gè)接口,本身的類圖還是比較簡單的,繼承了AttributeAccessor和BeanMetadataElement接口。

2.1 AttributeAccessor
AttributeAccessor接口代表一個(gè)屬性訪問器,它的作用是可以給Bean附加一些自定義的屬性,并提供訪問方法。
例如:originalTargetClass屬性代表AOP被代理的原始Class對(duì)象;preserveTargetClass屬性代表是否基于類進(jìn)行代理。
AttributeAccessorSupport是其中一個(gè)實(shí)現(xiàn)類,它底層通過LinkedHashMap來存儲(chǔ)這些附加屬性。
public interface AttributeAccessor {
void setAttribute(String name, @Nullable Object value);
Object getAttribute(String name);
Object removeAttribute(String name);
boolean hasAttribute(String name);
String[] attributeNames();
}2.2 BeanMetadataElement
BeanMetadataElement接口我也不是很清楚具體作用是啥,網(wǎng)上對(duì)它的介紹也比較少。
public interface BeanMetadataElement {
/**
* 對(duì)于常規(guī)Bean,可以獲得Bean對(duì)應(yīng)的Resource
*/
@Nullable
Object getSource();
}
經(jīng)過實(shí)驗(yàn)發(fā)現(xiàn),對(duì)于常規(guī)的Bean來說,可以通過getSource()方法獲取Bean對(duì)應(yīng)的資源。例如:現(xiàn)在有一個(gè)BeanDefinition它的BeanClass來自ClassPath下的包,getSource()方法可以獲取到這個(gè)Class文件對(duì)應(yīng)的FileSystemResource資源。
2.3 BeanDefinition
終于看到主角了,BeanDefinition還是一個(gè)接口,它提供了一系列方法來讀寫B(tài)ean的一些屬性定義,方法名基本都能見名知意,注釋里已經(jīng)把方法的作用寫上了。
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
/**
* 父Bean的name 對(duì)應(yīng)XML里的 <bean parent=""> 配置
*/
void setParentName(@Nullable String parentName);
String getParentName();
/**
* BeanClassName 對(duì)應(yīng)XML里的 <bean class=""> 配置
*/
void setBeanClassName(@Nullable String beanClassName);
String getBeanClassName();
/**
* Bean的作用域 單例/原型
*/
void setScope(@Nullable String scope);
String getScope();
/**
* 是否延遲加載
* 默認(rèn)為fale,容器啟動(dòng)時(shí)自動(dòng)實(shí)例化單例Bean
* 設(shè)置為true,則在getBean時(shí)再實(shí)例化
*/
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
/**
* 依賴的其它Bean
* BeanFactory保證先實(shí)例化依賴的Bean
*/
void setDependsOn(@Nullable String... dependsOn);
String[] getDependsOn();
/**
* 當(dāng)前Bean是否作為其它Bean依賴注入時(shí)的候選Bean,默認(rèn)為true
* Spring根據(jù)Type注入時(shí),如果存在多個(gè)實(shí)現(xiàn)類,會(huì)拋出異常
* 通過將autowireCandidate設(shè)置為false,該Bean將不再是依賴注入時(shí)的候選Bean
* 根據(jù)name注入時(shí),不受影響
*/
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
/**
* 依賴注入 存在多個(gè)候選Bean時(shí),優(yōu)先注入primary=true的
*/
void setPrimary(boolean primary);
boolean isPrimary();
void setFactoryBeanName(@Nullable String factoryBeanName);
String getFactoryBeanName();
void setFactoryMethodName(@Nullable String factoryMethodName);
String getFactoryMethodName();
/**
* Bean的構(gòu)造函數(shù)參數(shù)值
*/
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
/**
* 獲取Bean實(shí)例的屬性值
*/
MutablePropertyValues getPropertyValues();
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
/**
* Bean初始化的方法名
*/
void setInitMethodName(@Nullable String initMethodName);
@Nullable
String getInitMethodName();
/**
* Bean銷毀的方法名
*/
void setDestroyMethodName(@Nullable String destroyMethodName);
String getDestroyMethodName();
void setRole(int role);
int getRole();
/**
* Bean的描述
*/
void setDescription(@Nullable String description);
String getDescription();
/**
* 是否是單例的
*/
boolean isSingleton();
/**
* 是否是原型的
*/
boolean isPrototype();
/**
* 是否是抽象Bean,如果是將不會(huì)實(shí)例化
*/
boolean isAbstract();
@Nullable
String getResourceDescription();
/**
* 獲取原始的BeanDefinition
*/
@Nullable
BeanDefinition getOriginatingBeanDefinition();
}
2.4 AbstractBeanDefinition
AbstractBeanDefinition是一個(gè)抽象類,實(shí)現(xiàn)了絕大多數(shù)BeanDefinition的功能,源碼也很簡單,通過大量屬性來記錄BeanDefinition對(duì)應(yīng)方法設(shè)置的屬性值,代碼就不貼了。
2.5 GenericBeanDefinition
GenericBeanDefinition是一個(gè)類,它是BeanDefinition的標(biāo)準(zhǔn)實(shí)現(xiàn),繼承自AbstractBeanDefinition。剛剛已經(jīng)說過了,由于AbstractBeanDefinition已經(jīng)實(shí)現(xiàn)了絕大多數(shù)方法了,所以GenericBeanDefinition的代碼也極其簡單,只實(shí)現(xiàn)了一個(gè)讀寫parentName的方法。
2.6 AnnotatedGenericBeanDefinition
顧名思義,AnnotatedGenericBeanDefinition是一個(gè)基于注解的BeanDefinition標(biāo)準(zhǔn)實(shí)現(xiàn),它繼承自GenericBeanDefinition,已經(jīng)獲得了BeanDefinition完整的能力了。只不過,由于是基于注解的標(biāo)準(zhǔn)實(shí)現(xiàn),所以它還實(shí)現(xiàn)了AnnotatedBeanDefinition接口,以此來獲得獲取注解元數(shù)據(jù)的能力。
public interface AnnotatedBeanDefinition extends BeanDefinition {
// 獲取注解元數(shù)據(jù)
AnnotationMetadata getMetadata();
// 獲取工廠方法元數(shù)據(jù)的能力
MethodMetadata getFactoryMethodMetadata();
}
AnnotatedGenericBeanDefinition的代碼也同樣極其簡單,只是提供了兩個(gè)屬性metadata和factoryMethodMetadata來記錄注解元數(shù)據(jù)和工廠方法元數(shù)據(jù)而已。
2.7 其它實(shí)現(xiàn)
本文著重分析了AnnotatedGenericBeanDefinition這一條分支,實(shí)際上在Spring中BeanDefinition還有很多實(shí)現(xiàn)類,例如:
- RootBeanDefinition:ChildBeanDefinition:基于父Bean的子BeanDefinition。
- ConfigurationClassBeanDefinition:加了@Bean注解的BeanDefinition。
- ScannedGenericBeanDefinition:加了@Component及其派生注解的BeanDefinition。
到此這篇關(guān)于Spring BeanDefinition使用介紹的文章就介紹到這了,更多相關(guān)Spring BeanDefinition內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringIOC?BeanDefinition的加載流程詳解
- Spring注解驅(qū)動(dòng)之BeanDefinitionRegistryPostProcessor原理解析
- 如何利用Spring把元素解析成BeanDefinition對(duì)象
- Spring超詳細(xì)講解創(chuàng)建BeanDefinition流程
- BeanDefinitionRegistryPostProcessor如何動(dòng)態(tài)注冊(cè)Bean到Spring
- Spring Bean生命周期之BeanDefinition的合并過程詳解
- springboot自動(dòng)掃描添加的BeanDefinition源碼實(shí)例詳解
- Spring應(yīng)用拋出NoUniqueBeanDefinitionException異常的解決方案
相關(guān)文章
Java中用POI實(shí)現(xiàn)將數(shù)據(jù)導(dǎo)出到Excel
這篇文章主要介紹了Java中用POI實(shí)現(xiàn)將數(shù)據(jù)導(dǎo)出到Excel,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04
Java使用Tesseract-Ocr識(shí)別數(shù)字
這篇文章主要介紹了Java使用Tesseract-Ocr識(shí)別數(shù)字的方法,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下2021-04-04

