Spring <bean> 之间的关系&整合多个配置文件

Spring 不但可以通过 <ref>  引用另一个 Bean,建立起 Bean 和 Bean 之间的依赖关系,<bean> 元素标签之间也可以建立类似的关系,完成一些特殊的功能。

1.继承

OOP思想告诉我们,如果多个类拥有相同的方法和属性,则可以引入一个父类,在父类中定义这些类共同的方法和属性,以消除重复的代码。同样,如果多个 <bean> 存在相同的配置信息,则 Spring 允许定义一个父<bean>,子<bean>将自动继承父<bean>的配置信息。

下面通过一个实例,对使用和未使用父子<bean>的配置进行比较,从中看出父子<bean>给配置带来的便利性,如下所示。

未使用父子<bean>的配置

<bean id="car1" class="com.smart.tagdepend.Car"
    p:brand="红旗CA72" p:price="2000.00" p:color="黑色" />
<bean id="car2" class="com.smart.tagdepend.Car"
    p:brand="红旗CA72" p:price="2000.00" p:color="红色" />

上面代码配置了两个 car Bean,我们发现这两个 Bean 的配置存在大量的重复信息。事实上,二者除了 color 属性配置值不一样外,其他配置信息都相同。通过父子<bean>的继承关系就可以很好地消除这种重复的配置信息如下所示。

使用父子<bean>的配置

<!-- ①定义为抽象<bean> -->
<bean id="abstractCar" class="com.smart.tagdepend.Car"
  p:brand="红旗CA72" p:price="2000.00" p:color="黑色" abstract="true"/>
<!-- ②继承于abstractCar -->
<bean id="car3" parent="abstractCar">
  <property name="color" value="红色"/>
</bean>
<!-- ③继承于abstractCar -->
<bean id="car4" parent="abstractCar" >
  <property name="color" value="白色"/>
</bean>    

car3 和 car4 这两个 <bean> 都继承于 abstractCar 的 <bean>,Spring 会将父<bean>的配置信息传递给子<bean>。如果子<bean>提供了父<bean>已有的配置信息,那么子<bean>的配置信息将覆盖父<bean>的配置信息。

父<bean>的主要功能是简化子<bean>的配置,所以一般声明为 abstract="true",表示这个<bean>不实例化为一个对应的Bean。如果用户没有指定 abstract="true",则 Spring IOC容器会实例化一个名为 abstractCar 的 Bean。

2.依赖
一般情况下,可以使用 <ref> 元素标签建立对其他 Bean 的依赖关系,Spring 负责管理这些 Bean 的关系。当实例化一个 Bean 时,Spring 保证该 Bean 所依赖的其他 Bean 已经初始化。

但在某些情况下,这种 Bean 之间的依赖关系并不那么明显。下面举一个例子。“小春论坛”拥有很多系统参数(如会话过期时间、缓存更新时间等),这些系统参数用于控制系统的运行逻辑。我们用一个 SystemSettings 类表示这些系统参数。

public class SystemSettings {
   public static int SESSION_TIMEOUT = 30;
   public static int REFRESH_CYCLE = 60;
}

在 SystemSettings 类中为每个系统参数提供了默认值,但一个灵活的论坛必须提供一个管理后台,在管理后台中可以调整这些系统参数并保存到后台数据库中,在系统启动时,初始化程序从数据库后台加载这些系统参数的配置值以覆盖默认值。

public class SysInit {
   public SysInit(){
       System.out.println("SysInit");
       //模拟从数据库中加载系统设置信息
       SystemSettings.REFRESH_CYCLE = 100;
       SystemSettings.SESSION_TIMEOUT = 10;
   }
}

假设论坛有一个缓存刷新管理器,它需要根据系统参数 SystemSettings.REFRESH  CYCLE创建缓存刷新定时任务。

public class CacheManager {
   public CacheManager(){
       Timer timer = new Timer();
       TimerTask cacheTask = new CacheTask();
       timer.schedule(cacheTask,0,SystemSettings.REFRESH_CYCLE*1000);
   }
}

在以上实例中,CacheManager 依赖于 SystemSettings,而 SystemSettings 的值由 Syslnit 负责初始化。虽然 CacheManager 不直接依赖于 Syslnit,但从逻辑上看,CacheManager 希望在 Syslnit 加载并完成系统参数设置后再启动,以避免调用不到真实的系统参数值。如果这3个 Bean 都在 Spring 配置文件中定义,那么如何保证 Syslnit 在 CacheManager 之前进行初始化呢?

Spring 允许用户通过 depends-on 属性显式指定 Bean 前置依赖的 Bean,前置依赖的 Bean 会在本 Bean 实例化之前创建好。

<!-- <bean>的依赖 -->
<bean id="cacheManager" class="com.smart.tagdepend.CacheManager" depends-on="sysInit" />
<bean id="sysInit" class="com.smart.tagdepend.SysInit" />

通过 depends-on 属性将 syslnit 指定为 manager 前置依赖的 Bean,这样就可以保证 managerBean 在实例化并运行时所引用的系统参数是最新的设置值,而非 SystemSettings 类中的默认值。如果前置依赖于多个 Bean,则可以通过逗号、空格或分号的方式创建 Bean 的名称。

3.引用

假设一个<bean>要引用另一个<bean>的id属性值,则可以直接使用以下配置方式:

<!-- <bean>引用 -->
<bean id="car" class="com.smart.tagdepend.Car"/> ①
<bean id="boss" class="com.smart.tagdepend.Boss" >  ②
  <property name="carId"  >
    <value>car</value>
  </property>
</bean>

假设希望将 boss Bean 的 carld 设置为①处 <bean> 的 id 值,虽然可以通过②处的方式以字面值的形式进行设置,但二者之间并没有建立引用关系。一般情况下,在一个 Bean 中引用另一个 Bean 的 id 是希望在运行期通过 getBean(beanName) 方法获取对应的 Bean。由于 Spring 并不会在容器启动时对属性配置值进行特殊检查,因此,即使编写错误,也需要等到具体调用时才会发现。

Spring 为此提供了一个 <idref> 元素标签,可以通过 <idref> 引用另一个 <bean> 的名字。在容器启动时,Spring 负责检查引用关系的正确性,这样就可以提前发现错误。因此,下面的配置是推荐的优化方案:

<bean id="car" class="com.smart.tagdepend.Car"/>  ①
<bean id="boss" class="com.smart.tagdepend.Boss" >  ②
    <idref bean="car"/>
  </property>
</bean>

假设②处由于配置错误,误将 <idref bean="car"/> 写为 <idref bean="cat"/>,那么 Spring 容器在启动时,将会抛出 BeanDefinitionStoreException,提示容器中没有名为 cat 的 Bean

如果引用者和被引用者的 <bean> 位于同一个XML配置文件中,则可以使用 <idref local="car"> 的配置方式,这时IDE的XML分析器就可以在开发期发现引用错误了。

整合多个配置文件

对于一个大型应用来说,可能存在多个 XML 配置文件,在启动 Spring 容器时,可以通过一个 String 数组指定这些配置文件。Spring 还允许通过 <import> 将多个配置文件引入到一个文件中,进行配置文件的集成。这样,在启动 Spring 容器时,仅需指定这个合并好的配置文件即可。

<import resource="classpath:com/smart/impt/beans1.xml"/> ①
<bean id="boss1" class="com.smart.fb.Boss" p:name="John" p:car-ref="car1"/>
<bean id="boss2" class="com.smart.fb.Boss" p:name="John" p:car-ref="car2"/>

假设已经在 beans1.xml 中配置了 car1 和 car2 的 Bean,在①处通过 <import> 的 resource 属性引入 beans1.xml,beans2.xml 就拥有了完整的配置信息,Spring 容器仅需通过 beans2.xml 就可以加载所有的配置信息。

需要指出的是,如果一个配置文件 a.xml 定义的 <bean> 引用了另一个配置文件 b.xml 定义的 <bean>,那么并不一定需要通过 <import> 引入 b.xml,只需在启动 Spring 容器时,a.xml 和 b.xml 都在配置文件列表中即可。区别在于,如果 a.xml 采用 import 引入了 b.xml,相当于 a.xml 一个文件就包含了 a.xml 和 b.xml 两个文件的内容,因此 Spring 容器启动时仅需加载 a.xml 即可:否则就需要在启动 Spring 容器时,同时加载 a.xml 和 b.xml 配置文件,以便在内存中对 a.xml 和 b.xml 进行合并。

一个 XML 配置文件可以通过 <import> 组合多个外部的配置文件,resource 属性支持 Spring 标准的资源路径。

原文地址:https://www.cnblogs.com/jwen1994/p/11062209.html

时间: 2024-08-27 19:45:56

Spring <bean> 之间的关系&整合多个配置文件的相关文章

Spring Bean之间的关系

bean之间的关系:继承和依赖继承bean的配置 Spring允许继承bean的配置,被继承的bean称为父bean,继承这个父bean的bean称为子bean 子bean从父bean中继承配置,包括bean的属性配置 子bean也可以覆盖从父bean继承过来的配置 父bean可以作为配置模版,也可以作为bean实例,若只想把父bean作为模板,可以设置<bean>的abstract属性为true,这样Spring将不会实例化这个bean 并不是<bean>元素里的所有属性都会被继

spring bean之间的关系:继承;依赖

概要: ' 继承Bean配置 Spring同意继承bean的配置,被继承的bean称为父bean.继承这个父Bean的Bean称为子Bean 子Bean从父Bean中继承配置,包含Bean的属性配置 子Bean也能够覆盖从父Bean继承过来的配置 父Bean能够作为配置模版,也能够作为Bean实例,若仅仅想把父Bean作为模版,能够配置<bean>的abstract属性为true.这样Spring将不会实例化这个Bean 并非<bean>元素里的全部属性都会被继承.比方:autow

Spring初学之bean之间的关系和bean的作用域

一.bean之间的关系 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.o

Spring学习--Bean 之间的关系

Bean 之间的关系:继承.依赖. Bean 继承: Spring 允许继承 bean 的配置 , 被继承的 bean 称为父 bean , 继承这个父 bean 的 bean 称为子 bean. 子 bean 从父 bean 中继承配置 , 包括 bean 的属性配置. 子 bean 也可以覆盖从父 bean 继承过来的配置. 父 bean 可以作为配置模板 , 也可以作为 bean 实例.若只想把父 bean 作为模板 , 可以设置 <bean> 的 abstract 属性为 true ,

【Spring】IOC容器之bean之间的关系

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 本文主要讲了Spring中Bean之间的关系,分为继承.依赖和引用三个类型.文章中都分别有例子和用法分析. 一.继承Bean配置 Spring允许继承bean的配置 ,被继承的bean称为父bean,继承这个父Bean的Bean称为子Bean 子Bean从父Bean中继承配置,包括Bean的属性配置 子Bean也可以 覆盖 从父Bean继承过来的配置 父Bean可以作为配置模版,也可以作为B

3.spring:自动装配/Bean之间的关系/作用域/外部文件/spel/

1.自动装配/手动装配 xml配置文件里的bean自动装配 Spring IOC 容器里可以自动的装配Bean,需要做的仅仅是在<bean>的autowire属性里面指定自动装配模式 ->byType(根据类型自动进行装配):若IOC容器里需要有多个与目标Bean类型一样的Bean,在这种情况子下,Spring无法判定那个Bean合适,所以不能执行自动装配 ->byName(根据名称自动装配):必须将目标Bean的名称和属性名设置完全相同, ->constuuctor(通过是

峰Spring4学习(5)bean之间的关系和bean的作用范围

一.bean之间的关系: 1)继承: People.java实体类: package com.cy.entity; public class People { private int id; private String name; private int age; private String className; public int getId() { return id; } public void setId(int id) { this.id = id; } public Strin

Bean之间的关系

Bean之间的关系:继承:依赖 [继承Bean的配置] 1.Spring允许继承bean的配置,被继承的bean称为父bean.继承这个父bean的Bean称为子bean. 2.子Bean从父Bean中继承配置,包括Bean的属性配置. 3.子Bean也可以覆盖从父Bean继承过来的配置. /spring-1/src/beans-relation.xml: 1 <bean id="address" class="com.hk.beans.autowire.Address

XML配置里的Bean自动装配与Bean之间的关系

需要在<bean>的autowire属性里指定自动装配的模式 byType(根据类型自动装配) byName(根据名称自动装配) constructor(通过构造器自动装配) 名字须与属性名一致 byName根据Bean的名字和当前bean的setter风格的属性名进行自动装配,若有匹配的,则进行自动装配,没有则不装配 byType  根据bean的类型和当前bean的属性的类型进行自动装配 缺点:有一个以上的类型匹配的bean则抛异常 自动装配的缺点 不够灵活,不能两者兼而言之 Bean之间