• Spring-Context之九:在bean定义中使用继承


    定义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上自行下载。

  • 相关阅读:
    linux学习17 运维核心技能-Linux系统下用户权限管理
    linux学习16 Linux用户和组管理命令演练和实战应用
    linux学习15 Linux系统用户和组全面讲解
    linux学习14 Linux运维高级系统应用-glob通配及IO重定向
    linux学习13 Linux运维常用文件管理命令及系统变量基础
    linux学习12 bash的常见特性及文本查看命令实战
    linux学习11 Linux基础命令及命令历史
    linux学习10 Linux目录结构和根文件系统全面讲解
    【Hadoop离线基础总结】Hive调优手段
    【Hadoop离线基础总结】Hive的基本操作
  • 原文地址:https://www.cnblogs.com/huang0925/p/3644096.html
Copyright © 2020-2023  润新知