Spring 学习指南 第三章 bean的配置 (未完结)

Posted 乘风破浪会有时,直挂云帆济沧海

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 学习指南 第三章 bean的配置 (未完结)相关的知识,希望对你有一定的参考价值。

第三章 bean 的配置

? 在本章中,我们将介绍以下内容:

  1. bean 定义的继承:
  2. 如何解决 bean 类的构造函数的参数:
  3. 如何配置原始类型 (如 int 、float 等) 、集合类型(如 java.util.List、java.util.Map)等以及自定义类型 (如 Address ) 等的 bean 属性和构造函数参数;
  4. 如何通过使用 p 命名空间和 c 命名空间分别指定 bean 属性和构造参数来使用应用程序上下文 XML 文件变得简洁;
  5. Spring 的 FactoryBean 接口,运行编写自己的工厂类来创建 bean 实例;
  6. 模块化 bean 配置。
bean 定义的继承

? 我们在第一章和第二章中看到,应用程序上下文 XML 文件中的 bean 定义指定了 bean 类及其依赖项的完全限定名称。在某些场景下,为了使 bean 定义不那么冗长,你可能希望 bean 定义从另一个 bean 定义继承配置信息。下面介绍 MyBank 应用中这样的一个场景。

MyBank——bean 定义继承实例

? 在上一章中,我们了解到 MyBank 应用通过 DAO 来访问数据库。假设 MyBank 应用定义了一个可以与数据库交互的 DatabaseOperations 类,因此 MyBank 应用中的所有 DAO 都依赖于 DatabaseOperations 类来执行数据库操作,如下图所示。

技术图片

? 上图展示了 FixedDepositDao 和 PersonalBankingDao 类依赖于 DatabaseOperations 类。以下应用程序上下文 XML 文件展示了这些类的 bean 定义。

<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 实例。

? 如果应用程序中的 多个 bean 共享一组公共的配置 (属性、构造函数参数等),则可以创建一个 bean 定义,作为其他 bean 定义的父定义。在 personalBankingDao 和 fixedDepositDao bean定义中,公共的配置是 databaseOperations 属性。下面展示了 personalBankingDao 和 fixedDepositDao bean 定义如何从父 bean 定义继承 databaseOperations 属性。

<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 定义使用 元素定义 databaseOperations 依赖项。 元素的 parent 属性指定从中继承配置的 bean 定义的名称。由于 fixedDepositDao 和 personalBankingDao bean 定义中的 parent 属性值为 daoTemplate ,因此他们从 daoTemplate bean 定义继承了 databaseOperation 属性。

? 如果 元素的 abstract 特性值设置为 true , 则表示 bean 定义是抽象的。在上面 xml 中, daoTemplate bean 定义是抽象的。请注意,Spring 容器不会尝试创建一个与抽象 bean 定义相对应的 bean 。

注意:
    抽象 bean 不能作为其他 bean 定义的依赖项,也就是说,不能使用 <property> 或 <constructor-arg> 元素来引用抽象  bean 。

? 你可能已经注意到 daoTemplate bean 定义没有指定 class特性。如果父 bean 定义没有指定 class特性,则需要在子 bean 定义 (如 fixedDepositDao 和 personalBankingDao) 中指定 class 特性。注意,如果不指定 class 特性,则必须将 bean 定义为抽象的,以使 Spring 容器不会去尝试创建与之对应的 bean实例。

? 要验证 fixedDepositDao 和 personalBankingDao bean 定义是否继承了 daoTemplate bean 定义的 databaseOperations 属性。请执行下面的 java 代码。BankApp 类的 main 方法调用在 fixedDepositDao 和 personalBankingDao bean 中的方法,而这些 bean 调用 DatabaseOperations 实例上的方法。你会注意到,BankApp 的 main 方法成功运行。没有抛出任何异常。如果没有将 DatabaseOperations 实例注入 fixedDepositDao 和 personalBankingDao bean 中,那么代码将抛出 java.lang.NullPointerException。

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 定义继承一下配置信息:

  1. 属性,通过 元素指定。
  2. 构造函数参数,通过 元素指定。
  3. 方法覆盖(见4,5节)
  4. 初始化和销毁方法(见 第五章);
  5. 工厂方法,通过 元素的 工厂方法特性指定(见2,3节,了解静态和实例工厂方法如何用于创建 bean)

以上是关于Spring 学习指南 第三章 bean的配置 (未完结)的主要内容,如果未能解决你的问题,请参考以下文章

Spring:IOC/DI注解开发管理第三方bean

Spring掌握IOC/DI注解管理第三方bean

Spring Boot学习

学习笔记——Spring管理第三方bean;Spring中Bean的作用域;Spring中Bean的生命周期;Spring中bean的后置处理器;Spring中自动装配

Spring框架学习教程,详解Spring注入bean的几种方式

Spring学习-----Spring bean配置继承