Spring BeanDefinition使用介紹
1. 前言
Spring最重要的一個(gè)概念當(dāng)屬Bean了,我們寫的Controller、Service、Dao凡是加了對應(yīng)注解交給Spring管理的,都是Spring容器中的一個(gè)Bean。把我們自己寫的類變成一個(gè)Bean交給Spring管理有很多的好處,比如我們不用自己去new對象了,Spring會幫我們在適當(dāng)?shù)臅r(shí)候去實(shí)例化對象;再比如Spring還會維護(hù)Bean的依賴關(guān)系,自動注入依賴的對象;再比如Spring還可以基于Bean生成代理對象,來對原生的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對象;preserveTargetClass
屬性代表是否基于類進(jìn)行代理。
AttributeAccessorSupport是其中一個(gè)實(shí)現(xiàn)類,它底層通過LinkedHashMap
來存儲這些附加屬性。
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)上對它的介紹也比較少。
public interface BeanMetadataElement { /** * 對于常規(guī)Bean,可以獲得Bean對應(yīng)的Resource */ @Nullable Object getSource(); }
經(jīng)過實(shí)驗(yàn)發(fā)現(xiàn),對于常規(guī)的Bean來說,可以通過getSource()
方法獲取Bean對應(yīng)的資源。例如:現(xiàn)在有一個(gè)BeanDefinition它的BeanClass來自ClassPath下的包,getSource()方法可以獲取到這個(gè)Class文件對應(yīng)的FileSystemResource資源。
2.3 BeanDefinition
終于看到主角了,BeanDefinition還是一個(gè)接口,它提供了一系列方法來讀寫B(tài)ean的一些屬性定義,方法名基本都能見名知意,注釋里已經(jīng)把方法的作用寫上了。
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement { /** * 父Bean的name 對應(yīng)XML里的 <bean parent=""> 配置 */ void setParentName(@Nullable String parentName); String getParentName(); /** * BeanClassName 對應(yīng)XML里的 <bean class=""> 配置 */ void setBeanClassName(@Nullable String beanClassName); String getBeanClassName(); /** * Bean的作用域 單例/原型 */ void setScope(@Nullable String scope); String getScope(); /** * 是否延遲加載 * 默認(rèn)為fale,容器啟動時(shí)自動實(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)類,會拋出異常 * 通過將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,如果是將不會實(shí)例化 */ boolean isAbstract(); @Nullable String getResourceDescription(); /** * 獲取原始的BeanDefinition */ @Nullable BeanDefinition getOriginatingBeanDefinition(); }
2.4 AbstractBeanDefinition
AbstractBeanDefinition是一個(gè)抽象類,實(shí)現(xiàn)了絕大多數(shù)BeanDefinition的功能,源碼也很簡單,通過大量屬性來記錄BeanDefinition對應(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringIOC?BeanDefinition的加載流程詳解
- Spring注解驅(qū)動之BeanDefinitionRegistryPostProcessor原理解析
- 如何利用Spring把元素解析成BeanDefinition對象
- Spring超詳細(xì)講解創(chuàng)建BeanDefinition流程
- BeanDefinitionRegistryPostProcessor如何動態(tài)注冊Bean到Spring
- Spring Bean生命周期之BeanDefinition的合并過程詳解
- springboot自動掃描添加的BeanDefinition源碼實(shí)例詳解
- Spring應(yīng)用拋出NoUniqueBeanDefinitionException異常的解決方案
相關(guān)文章
基于web項(xiàng)目log日志指定輸出文件位置配置方法
下面小編就為大家分享一篇基于web項(xiàng)目log日志指定輸出文件位置配置方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04java使用Logback配置輸出日志內(nèi)容到文件示例代碼
這篇文章主要介紹了java?Logback輸出日志內(nèi)容到文件,要將logger.info的信息輸出到文件,您可以使用Logback配置,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09詳解JAVA抓取網(wǎng)頁的圖片,JAVA利用正則表達(dá)式抓取網(wǎng)站圖片
這篇文章主要介紹了詳解JAVA抓取網(wǎng)頁的圖片,JAVA利用正則表達(dá)式抓取網(wǎng)站圖片,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2016-12-12利用Java代碼實(shí)現(xiàn)區(qū)塊鏈技術(shù)
這篇文章主要介紹了利用Java代碼實(shí)現(xiàn)區(qū)塊鏈技術(shù),區(qū)塊鏈的應(yīng)用范圍幾乎無窮無盡,關(guān)于區(qū)塊鏈?zhǔn)侨绾芜\(yùn)作的,下文來看看具體的內(nèi)容介紹吧,需要的朋友可以參考一下2022-04-04Java 最優(yōu)二叉樹的哈夫曼算法的簡單實(shí)現(xiàn)
這篇文章主要介紹了Java 最優(yōu)二叉樹的哈夫曼算法的簡單實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10