在本章中,咱们将介绍如下内容:java
咱们在第一章和第二章中看到,应用程序上下文 XML 文件中的 bean 定义指定了 bean 类及其依赖项的彻底限定名称。在某些场景下,为了使 bean 定义不那么冗长,你可能但愿 bean 定义从另外一个 bean 定义继承配置信息。下面介绍 MyBank 应用中这样的一个场景。spring
在上一章中,咱们了解到 MyBank 应用经过 DAO 来访问数据库。假设 MyBank 应用定义了一个能够与数据库交互的 DatabaseOperations 类,所以 MyBank 应用中的全部 DAO 都依赖于 DatabaseOperations 类来执行数据库操做,以下图所示。数据库
上图展现了 FixedDepositDao 和 PersonalBankingDao 类依赖于 DatabaseOperations 类。如下应用程序上下文 XML 文件展现了这些类的 bean 定义。apache
<bean id="databaseOperations" class="sample.spring.chapter01.bankapp.utils.DatabaseOperations"></bean> <bean id="personalBankingDao" class="sample.spring.chapter01.bankapp.dao.PersonalBankingDaoImpl"> <property name="databaseOperations" ref="databaseOperations" /> </bean> <bean id="fixedDepositDao" class="sample.spring.chapter01.bankapp.dao.FixedDepositDaoImpl"> <property name="databaseOperations" ref="databaseOperations" /> </bean>
上面 xml 中,personalBankingDao 和 fixedDepositDao bean 定义都使用 databaseOperations 属性来引用 DatabaseOperations 实例。这意味着 PersonalBankingDaoImpl 和 FixedDepositDaoImpl 类都定义了一个 setDatabaseOperations 方法,以容许 Spring 容器注入 DatabaseOperations 实例。app
若是应用程序中的 多个 bean 共享一组公共的配置 (属性、构造函数参数等),则能够建立一个 bean 定义,做为其余 bean 定义的父定义。在 personalBankingDao 和 fixedDepositDao bean定义中,公共的配置是 databaseOperations 属性。下面展现了 personalBankingDao 和 fixedDepositDao bean 定义如何从父 bean 定义继承 databaseOperations 属性。dom
<bean id="databaseOperations" class="sample.spring.chapter03.bankapp.utils.DatabaseOperations"></bean> <bean id="daoTemplate" abstract="true"> <property name="databaseOperations" ref="databaseOperations" /> </bean> <bean id="fixedDepositDao" parent="daoTemplate" class="sample.spring.chapter03.bankapp.dao.FixedDepositDaoImpl"> </bean> <bean id="personalBankingDao" parent="daoTemplate" class="sample.spring.chapter03.bankapp.dao.PersonalBankingDaoImpl"></bean>
在上面的 xml 中,daoTemplate bean 定义了 fixedDepositDao 和 personalBankingDao bean 定义共享的公共配置。因为 fixedDepositDao 和 personalBankingDao bean 定义都须要 databaseOperations 依赖项,daoTemplate bean 定义使用
若是
注意: 抽象 bean 不能做为其余 bean 定义的依赖项,也就是说,不能使用 <property> 或 <constructor-arg> 元素来引用抽象 bean 。
你可能已经注意到 daoTemplate bean 定义没有指定 class特性。若是父 bean 定义没有指定 class特性,则须要在子 bean 定义 (如 fixedDepositDao 和 personalBankingDao) 中指定 class 特性。注意,若是不指定 class 特性,则必须将 bean 定义为抽象的,以使 Spring 容器不会去尝试建立与之对应的 bean实例。spa
要验证 fixedDepositDao 和 personalBankingDao bean 定义是否继承了 daoTemplate bean 定义的 databaseOperations 属性。请执行下面的 java 代码。BankApp 类的 main 方法调用在 fixedDepositDao 和 personalBankingDao bean 中的方法,而这些 bean 调用 DatabaseOperations 实例上的方法。你会注意到,BankApp 的 main 方法成功运行。没有抛出任何异常。若是没有将 DatabaseOperations 实例注入 fixedDepositDao 和 personalBankingDao bean 中,那么代码将抛出 java.lang.NullPointerException。3d
package sample.spring.chapter03.bankapp; import org.apache.log4j.Logger; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import sample.spring.chapter03.bankapp.controller.FixedDepositController; import sample.spring.chapter03.bankapp.controller.PersonalBankingController; import sample.spring.chapter03.bankapp.domain.FixedDepositDetails; public class BankApp { private static Logger logger = Logger.getLogger(BankApp.class); public static void main(String args[]) { ApplicationContext context = new ClassPathXmlApplicationContext( "classpath:META-INF/spring/applicationContext.xml"); FixedDepositController fixedDepositController = context .getBean(FixedDepositController.class); fixedDepositController.submit(context .getBean(FixedDepositDetails.class).setDepositAmount(100) .setEmail("someemail@somedomain.com").setId(1).setTenure(10)); logger.info("Your fixed deposit details : " + fixedDepositController.get()); PersonalBankingController personalBankingController = context .getBean(PersonalBankingController.class); logger.info(personalBankingController.getMiniStatement()); } }
下图 显示了 fixedDepositDao 和 personalBankingDao bean 定义中,bean 定义继承是如何工做的
上图展现了 fixedDepositDao 和 personalBankingDao bean 定义从 daoTemplate bean 定义继承了 databaseOperations 属性(以 fixedDeopsitDa 和 personalBankingDao 标识的方框中的 property 属性)。上图还描述了 Spring 容器不会尝试建立 与 daoTemplate bean 定义相对应的bean 实例,由于他被标记为 abstract。
子 bean 定义从 父 bean 定义继承一下配置信息: