在工作中碰到了好多的配置文件,具體來說是spring 中bean配置的parent的配置,搞的我一頭霧水,仔細看一下spring中有關bean的配置,剖析一下,具體什么含義!
一、Spring IoC容器和beans的介紹
1、Spring框架實現控制反轉(IoC)的原理。IoC又叫依賴注入(DI)。它描述了對象的定義和依賴的一個過程,也就是說,依賴的對象通過構造參數、工 廠方法參數或者屬性注入,當對象實例化后依賴的對象才被創建,當創建bean后容 器注入這些依賴對象。這個過程基本上是反向的,因此命名為控制反轉(IoC),它通過直接使用構造類來控制實例化,或者定義它們之間的依賴關系,或者類似於服務定位模式的一種機制。
2、org.springframework.beans 和 org.springframework.context 是Spring框 架中IoC容器的基礎, BeanFactory 接口提供一種高級的配置機制能夠管理任何 類型的對象。 ApplicationContext 是 BeanFactory 的子接口。它能更容易集 成Spring的AOP功能、消息資源處理(比如在國際化中使用)、事件發布和特定的 上下文應用層比如在網站應用中的 WebApplicationContext。 總之, BeanFactory 提供了配置框架和基本方法, ApplicationContext 添加 更多的企業特定的功能。 ApplicationContext 是 BeanFactory 的一個子接 口,在本章它被專門用於Spring的IoC容器描述。
3、在Spring中,由Spring IoC容器管理的對象叫做beans。 bean就是由Spring IoC容 器實例化、組裝和以其他方式管理的對象。此外bean只是你應用中許多對象中的一 個。Beans以及他們之間的依賴關系是通過容器配置元數據反映出來。
二、spring中容器的介紹
1、org.springframework.context.ApplicationContext 接口代表了Spring Ioc容 器,它負責實例化、配置、組裝之前的beans。容器通過讀取配置元數據獲取對象 的實例化、配置和組裝的描述信息。它配置的0元數據用xml、Java注解或Java代碼 表示。它允許你表示組成你應用的對象以及這些對象之間豐富的內部依賴關系。
2、Spring提供幾個開箱即用的 ApplicationContext 接口的實現類。在獨立應用程 序中通常創建一 個 ClassPathXmlApplicationContext 或 FileSystemXmlApplicationContext 實例對象。雖然XML是用於定義配置元數據的傳統格式,你也可以指示容器使用 Java注解或代碼作為元數據格式,但要通過提供少量XML配置來聲明啟用對這些附 加元數據格式的支持。
3、在大多數應用場景中,顯示用戶代碼不需要實例化一個或多個Spring IoC容器的實 例。
三、bean 中的parent屬性
這個在spring-framework 5.0官方文檔中都很少見,但是在文檔中還是有一點定義的,在定義事務代理的一個小塊中找到了一點,也就值找到了這一點,呵呵了。。。
1、創建代理的父模板
特別是在定義事務代理時,最終可能有許多類似的代理定義。 使用父、子bean定 義,以及內部bean定義,可能會使代理的定義更加清晰和簡明。
1 //定義代理父模板 2 <bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> 3 <property name="transactionManager" ref="transactionManager"/> 4 <property name="transactionAttributes"> 5 <props> 6 <prop key="*">PROPAGATION_REQUIRED</prop> 7 </props> 8 </property> 9 </bean>
這個定義自身永遠不會實例化,所以實際上是不完整的定義。 然后每個需要被創建的代理,只需要一個子bean的定義,將目標對象包裝成一個內部類定義,因為目標對象永遠不會直接被使用。
2、創建子bean
1 //簡單的子bean定義 2 <bean id="myService" parent="txProxyTemplate"> 3 <property name="target"> 4 <bean class="org.springframework.samples.MyServiceImpl"> 5 </bean> 6 </property> 7 </bean>
當然也可以覆蓋父模板的屬性,例如在本示例中,事務傳播的設置:
1 <bean id="mySpecialService" parent="txProxyTemplate"> 2 <property name="target"> 3 <bean class="org.springframework.samples.MySpecialServiceImpl"> 4 </bean> 4 </property> 4 <property name="transactionAttributes"> 7 <props> 7 <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> 8 <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> 9 <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop> 10 <prop key="store*">PROPAGATION_REQUIRED</prop> 11 </props> 12 </property> 13 </bean>
需要主意的是,在上面的示例中,我們通過 abstract 屬性明確的將父bean標記為抽象定義, 就如前面介紹的子bean定義,因此該父bean永遠不會被實例化。 應用上下文(不是簡單的bean工廠)默認會預先實例化所有單例。 因此,重要的是,如果你有一個僅僅想作為模板的bean(父bean)定義,並且指定了該bean的 class, 那么你必須保證該bean的 abstract 屬性被置為 tue ,否則應用上下文 會嘗試在實際中預先實例化該bean。
總結:這個用法的好處就是可以優化代碼,很多相同的代碼可以抽取出來,直接放到父bean中,然后在子bean中增加一些獨特的屬性或者方法,簡單整潔,擴展性強,但是,這里並不是繼承關系,並不是extends,spring官方文檔說是子bean將目標對象包裝成一個內部類定義,這個具體在內存中如何存儲以及調用不是很明白,這里存在一點點的問題,記錄下來,我再研究一下內部類!!!
Java中的內部類:
內部類的訪問特點:
A:內部類可以直接訪問外部類的成員,包括私有。
B:外部類要訪問內部類的成員,必須創建對象。