在Spring容器中,两个Bean之间 除了注入关系外,还存在 继承、依赖、引用 三种关系:
- 继承关系:在Spring容器当中允许使用abstract标签来定义一个父bean,parent标签来定义一个子bean。子bean将自动继承父bean的配置信息。
- 依赖关系:Spring允许用户通过depends-on标签来设定bean的前置依赖bean,前置依赖的bean会在本bean实例化之前就创建好,来供本bean使用。
- 引用关系:我们不光可以通过ref标签来引用其他的bean,而且可以通过idref标签来引用其他bean的名字。他的主要作用是:在Spring容器启动的时候就可以检查引用关系的正确性。那么这样就可以提前发现配置信息是否存在错误。
一.继承关系
在面向对象的编程原理中,当多个类拥有相同的方法和属性,则可以引入父类消除代码重复。
在Spring容器中,如果多个Bean存在相同的配置信息,同样可以定义一个父Bean,子Bean将自动继承父Bean的配置信息。父bean中的所有属性值也会出现在子bean当中,那么假如子bean当中配置了父bean已有的属性的话,会覆盖掉父bean中的配置。
配置为父bean的bean当中的abstract属性值得赋值为true
我们来看一个示例:
1. 未使用父子<bean>的配置
<bean id=“car1” class=“cn.lovepi.***.Car”
p:brand=“奔驰E300” p:price=“2000” p:color=“黑色”/>
<bean id=“car1” class=“cn.lovepi.***.Car”
p:brand=“奔驰E300” p:price=“2000” p:color=“红色”/>
可以看到,两个car bean除了color属性不同之外,其他属性都是完全一样的。
2. 使用父子<bean>的配置
<bean id=“abstractCar” class=“cn.lovepi.***.Car”
p:brand=“奔驰E300” p:price=“2000” p:color=“黑色” abstract=“true”/>
<bean id=“car1” p:color=“红色” parent=“abstractCar” />
<bean id=“car1” p:color=“白色” parent=“abstractCar” />
可以看到car1和car2这两个bean都继承自abstractCar这个父bean,在上面的代码中子bean就只改变了color属性,其他属性都跟父类相同。
二.依赖关系
在Spring容器中,当使用depends-on标签建立对其他Bean的依赖关系时,Spring容器负责管理这些Bean的关系,当实例化一个Bean时,容器保证该Bean所依赖的Bean已经初始化;如果前置依赖多个Bean,可以通过逗号或空格方式配置Bean名称。
我们来看一个示例:
在某论坛系统当中,具有很多的启动参数,比如:会话过期时间、缓存更新时间等。这些启动参数用来控制系统的运行逻辑,我们使用一个SystemSetting类来表示这些参数。
public class SystemSetting{
public static int SESSION_TIMEOUT = 30;
public static int REFRESH_CYCLE = 60;
}
在这里我们定义了两个系统参数,我们这里直接定义了这两个参数的值,但在真正的论坛系统当中这些值应该是可以动态设置的,并及时保存到后台数据库当中。在系统启动时,初始化程序来从后台数据库获取这些系统参数的配置值以覆盖默认的值。
在这里我们模拟从数据库中加载系统值。
public class SysInit{
public SysInit() {
SystemSettings.SESSION_TIMEOUT = 10;
SystemSettings.REFRESH_CYCLE = 100; }
}
假设我们的系统需要一个缓存刷新管理器,他需要根据SystemSettings.REFRESH_CYCLE 的值来创建缓存定时刷新任务,那么请看如下 的代码:
public class CacheManager {
public CacheManager(){
Timer timer = new Timer();
TimerTask cacheTask = new CacheTask();
timer.schedule(cachetask,0,SystemSettings.REFRESH_CYCLE);
}
}
在以上的三段代码中,CacheManager依赖与SystemSetting,而SystemSetting又依赖与SysInit。
可以看到SysInit必须首先执行然后才能执行接下来的代码。
如果这三个bean都在Spring当中定义,那么我们该如何保证SysInit bean被首先执行呢?
那么就得使用depends-on属性标签了
<bean id=“manager” class=“cn.lovepi.***.CacheManager”depends-on=“sysInit”/>
<bean id=“sysInit” class=“cn.lovepi.***.SysInit” />
三.引用关系
在Spring容器中,当使用<ref>标签引用另外一个Bean时,但实际上两者并没有建立引用关系,即使我们编写错误,也需要在运行期才可以发现。
因此Spring提供了<idref>元素标签,通过<idref>引用另一个Bean的名字,可以在容器启动的时候,检查引用关系的正确性,这样可以提前发现错误的配置信息
1. 常规配置方法
<bean id=“car” class=“cn.lovepi.***.Car”/>
<bean id=“boss” class=“cn.lovepi.***.Boss”
p:carId=“car” scope=“prototype” />
2. <idref>配置方法
<bean id=“car” class=“cn.lovepi.***.Car”/>
<bean id=“boss” class=“cn.lovepi.***.Boss” >
<property name=“carId”>
<idref bean=“car”/>
</property>
</bean>
总结:
Spring为bean提供了一系列的关系:注入、继承、依赖、引用
使用bean之间的关系可以将代码中繁琐的类间关系转移到配置文件当中来,降低了代码的耦合性,也方便系统的模块化管理。