定义bean时有个abstract属性,可以设置为true或false,默认为false。

1
2
3
4
<bean id="animal" class="Animal" abstract="true">
<property name="name" value="elephant"/>
<property name="legs" value="4”/>
</bean>

这里定义了一个叫elepahnt的animal bean,有4条腿,它与其他bean不同之处是abstract属性为true。这意味着什么?意味着这个bean不能被实例化,不能通过ApplicationContext.getBean()的方式来获取到该bean,也不能使用ref属性引用这个bean。否则会抛出BeanIsAbstractException的异常。

你可能会问?坑爹那?声明一个bean不能被实例化,那有何用?

当然有用,Spring框架开发者也不是一帮吃饱了没事干的人,设计一些没用的功能出来。

这要配合着parent属性来用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="animal" class="Animal" abstract="true">
<property name="legs" value="4"/>
</bean> <bean id="monkey" parent="animal">
<property name="name" value="dudu"/>
</bean> </beans>

这里有两个bean,一个是animal,指定legs是4,另一个是monkey,通过parent的属性指向animal,指定name为dudu。聪明的读者可能已经猜出来了,parent属性就是子bean可以继承父bean中的属性,并且在子bean中可以重载对应的属性。虽然我们没显式的指定monkey的legs为4,其实它已经从父bean animal中继承了这个属性。这样的好处是如果在定义大量bean时,发先大量bean存在重复属性定义时,可以抽取一个抽象bean出来,实现这些重复的属性定义,让其他bean都使用parent属性指向这个抽象bean。这样可以大大简化bean的配置。

除了使用parent直接引用父bean的class外,另外也可以使用自定义的class。

Monkey.java
1
2
3
4
5
6
7
8
9
10
11
12
public class Monkey extends Animal {

    private boolean canDrawing;

    public boolean isCanDrawing() {
return canDrawing;
} public void setCanDrawing(boolean canDrawing) {
this.canDrawing = canDrawing;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="animal" class="Animal" abstract="true">
<property name="legs" value="4"/>
</bean> <bean id="smartMonkey" class="Monkey" parent="animal">
<property name="name" value="smallDudu"/>
<property name="canDrawing" value="true"/>
</bean> </beans>

这样smartMonkey自动继承了父bean中的legs属性,同时它的class类型也是一个新类型。

有人可能要问了,子bean的class与父bean中的class一定要是继承关系吗?答案是否定的。
请看这个修改后的Monkey class,其本身并未从Animal继承。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Monkey {

    private boolean canDrawing;
private String name;
private int legs; public boolean isCanDrawing() {
return canDrawing;
} public void setCanDrawing(boolean canDrawing) {
this.canDrawing = canDrawing;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getLegs() {
return legs;
} public void setLegs(int legs) {
this.legs = legs;
}
}

然后还配置同样的bean。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="animal" class="Animal" abstract="true">
<property name="legs" value="4"/>
</bean> <bean id="smartMonkey" class="Monkey" parent="animal">
<property name="name" value="smallDudu"/>
<property name="canDrawing" value="true"/>
</bean> </beans>

依然能够正常工作,并且smartMonkey中的legs还是4。

这说明了Spring中使用parent继承父bean中的属性并不需要子bean和父bean的class在一个继承树上。父bean更像一个模板,子bean能够自动使用父bean中的配置而已。唯一需要注意的是在父bean中定义的属性在子bean中都要存在。

那可能有人就有个大胆的猜想了,可不可以定义一个没有class类型的父bean那?这个bean反正不能实例化,只用来让子bean继承属性。答案是肯定的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="animal" abstract="true">
<property name="legs" value="4"/>
</bean> <bean id="monkey" parent="animal" class="Animal">
<property name="name" value="dudu"/>
</bean> <bean id="smartMonkey" class="Monkey" parent="animal">
<property name="name" value="smallDudu"/>
<property name="canDrawing" value="true"/>
</bean> </beans>

上面的定义依然可以工作。

多说一点,parent也支持对集合属性的继承。比如在父bean中定义了一个属性为List或Map,子bean中也能继承到该List或Map,更强大的是子bean还可以对List或Map进行合并。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="sampleAccounts" abstract="true">
<property name="accounts">
<map>
<entry key="Bob" value="001"/>
<entry key="John" value="002"/>
</map>
</property>
</bean> <bean id="accountService" parent="sampleAccounts" class="AccountService">
<property name="accounts">
<map merge="true">
<entry key="Michael" value="003"/>
<entry key="Joel" value="004"/>
</map>
</property>
</bean> </beans>

在子bean中使用的map元素上使用merge=“true”就可以和父bean中的map条目进行合并。如果指定为false则不会合并,只会使用子bean中定义的map条目。

本例中的源码请在我的GitHub上自行下载。

Spring-Context之九:在bean定义中使用继承的更多相关文章

  1. 开涛spring3(5.4) - Spring表达式语言 之 5.4在Bean定义中使用EL

    5.4.1  xml风格的配置 SpEL支持在Bean定义时注入,默认使用“#{SpEL表达式}”表示,其中“#root”根对象默认可以认为是 ApplicationContext,只有Applica ...

  2. Spring3: 在Bean定义中使用EL-表达式语言

    5.4.1  xml风格的配置 SpEL支持在Bean定义时注入,默认使用“#{SpEL表达式}”表示,其中“#root”根对象默认可以认为是ApplicationContext,只有Applicat ...

  3. Spring表达式语言 之 5.4在Bean定义中使用EL(拾伍)

    5.4.1  xml风格的配置 SpEL支持在Bean定义时注入,默认使用"#{SpEL表达式}"表示,其中"#root"根对象默认可以认为是Applicati ...

  4. Spring基础——IOC九种bean声明方式

    Spring简介 Spring不是服务于开发web项目的功能,或业务.而是服务于项目的开发,方便各层间的解耦调用,方便对类的批量管理,是提高软件开发效率,降低后期维护成本的框架. Spring的核心思 ...

  5. 我该如何学习spring源码以及解析bean定义的注册

    如何学习spring源码 前言 本文属于spring源码解析的系列文章之一,文章主要是介绍如何学习spring的源码,希望能够最大限度的帮助到有需要的人.文章总体难度不大,但比较繁重,学习时一定要耐住 ...

  6. 品Spring:SpringBoot轻松取胜bean定义注册的“第一阶段”

    上一篇文章强调了bean定义注册占Spring应用的半壁江山.而且详细介绍了两个重量级的注册bean定义的类. 今天就以SpringBoot为例,来看看整个SpringBoot应用的bean定义是如何 ...

  7. 【Spring源码解读】bean标签中的属性

    说明 今天在阅读Spring源码的时候,发现在加载xml中的bean时,解析了很多标签,其中有常用的如:scope.autowire.lazy-init.init-method.destroy-met ...

  8. 【Spring源码解读】bean标签中的属性(二)你可能还不够了解的 abstract 属性和 parent 属性

    abstract 属性说明 abstract 在java的语义里是代表抽象的意思,用来说明被修饰的类是抽象类.在Spring中bean标签里的 abstract 的含义其实也差不多,表示当前bean是 ...

  9. 【Spring源码解读】bean标签中的属性(一)你可能还不够了解的 scope 属性

    scope 属性说明 在spring中,在xml中定义bean时,scope属性是用来声明bean的作用域的.对于这个属性,你也许已经很熟悉了,singleton和prototype信手捏来,甚至还能 ...

随机推荐

  1. [13]APUE:KQUEUE / FreeBSD

    [a] 概述 kqueue API 由两个函数(kqueue.kevent).一个辅助宏(EV_SET).一个结构体(struct kevent)构成,可以应用于 socket.FIFO.pipe.a ...

  2. mac 10.11.6,Xcode8下,ruby2.3安装,Cocoapods安装~

    适用环境 mac: 10.11.6 Xcode:8.1 命令执行步骤(安装ruby2.3前准备工作) 查看ruby更新源 gem sources  -L 删除默认官方或者淘宝,新增 https://g ...

  3. JS-Number

    Number 是对原始数据的封装 语法: var myNum=new Number(value);//返回一个新创建的 Number 对象 var myNum=Number(value);//把自己的 ...

  4. java中double变量保留小数问题

    (转载自玄影池扁舟) 做java项目的时候可能经常会遇到double类型变量保留小数的问题,下面便把我的经验做个简短的总结: java中double类型变量保留小数问题大体分两种情况: (一):小数点 ...

  5. oracle DBMS_LOCK.SLEEP()的使用

    create or replace procedure times isii positive:=1;beginloop dbms_lock.sleep(1);dbms_output.put_line ...

  6. iptables之LOG目标 被拦截包分析

    iptables之LOG目标 问题 在iptables的INPUT链中发现有大量未知包被拦截,这种情况就有两种可能,一是自己的某个服务的iptables端口没有打开,二是服务器正在遭受攻击 分析 这就 ...

  7. 快手4.0 (KSCAD)

    快手 4.0 (KSCAD) 是一款简单易用的矢量绘图软件,其功能和Visio类似,可以绘制工艺流程图,流程图.组织结构图.网络拓扑图.思维导图.商业图表等. 经过二次开发,可以应用于各种领域的图形化 ...

  8. GERBER文件

    GERBER文件 GERBER文件是一种国际标准的光绘格式文件,它包含RS-274-D和RS-274-X两种格式,其中RS-274-D称为基本GERBER格式,并 要同时附带D码文件才能完整描述一张图 ...

  9. 关于mock server

    这篇技术博客是在知乎上看到的 知乎js大神张云龙写的 这里贴过来记录下,如果侵权 请告知将及时删除. --------------------------- 为了更好的分工合作,让前端能在不依赖后端环 ...

  10. 我对C#的理解

    C#里面所有东西都可以看作对象.接口,类,枚举等等. 类是最常用的,可以继承别的接口,类等,就会自动拥有别人的功能. 接口是类的概要.给别人看的协议,好像一个人对外做出的承诺. 抽象类是实现了部分承诺 ...