Spring基础——Bean定义的继承(Bean配置中的parent属性)

本文介绍了如何在Spring框架中使用Bean的继承特性,通过父Bean传递配置信息,子Bean继承并可覆盖这些配置,以及抽象Bean的使用场景和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Bean的继承

  • 当一个Bean中定义了很多配置信息,可以将一部分固定信息抽象成父Bean,子Bean从父Bean继承配置数据,并根据需要可以覆盖或添加其他数据,这样可以使开发变的更加高效。

父Bean的定义

  • 父Bean所定义的配置属性子Bean必须完全兼容,也就是说子Bean必须要包含父Bean所有的配置属性,在配置的类中,可以是通过继承的方式实现,也可以是在类里包含所有属性来实现。
  • 父Bean的定义类
public class ParentBean {
    private String name;
    private String password;

    public void setName(String name) {
        this.name = name;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "ParentBean{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    public String getPassword() {
        return password;
    }
}
  • 子BeanA,通过继承的方式兼容父Bean所有属性
public class SonBeanA extends ParentBean {
    private int connectNum;
    private int timeout;
    private int poolMax;

    public void setConnectNum(int connectNum) {
        this.connectNum = connectNum;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public void setPoolMax(int poolMax) {
        this.poolMax = poolMax;
    }

    @Override
    public String toString() {
        return "SonBean{" +
                "name=" + getName() +
                ", password" + getPassword() +
                ", connectNum=" + connectNum +
                ", timeout=" + timeout +
                ", poolMax=" + poolMax +
                '}';
    }
}
  • 子BeanB,添加父Bean中所有的属性来达成兼容
public class SonBeanB {
    //    private ParentBean parentBean;
    private String tools;

    private String password;

    @Override
    public String toString() {
        return "SonBeanB{" +
                "tools='" + tools + '\'' +
                ", password='" + password + '\'' +
                ", name='" + name + '\'' +
                '}';
    }

    public void setPassword(String password) {
        this.password = password;
    }

    private String name;

    public void setName(String name) {
        this.name = name;
    }


    public void setTools(String tools) {
        this.tools = tools;
    }

}

XML配置parent属性继承父Bean

  • 父Bean并不一定是要指代抽象成父类,在由子类继承,可以直接通过parent属性来表示子Bean的定义继承
<!-- 父Bean定义 -->
<bean id="parentBean02" class="com.nobugnolife.bean.impl.ParentBean">
    <property name="name" value="redis"/>
    <property name="password" value="google"/>
</bean>


<!-- 子Bean通过parent继承父Bean的配置属性,并可以覆盖 -->
<bean id="sonBeanA02" class="com.nobugnolife.bean.impl.SonBeanA" parent="parentBean02">
    <property name="connectNum" value="20"/>
    <property name="timeout" value="100"/>
    <property name="poolMax" value="200"/>
    <!-- 覆盖父Bean的配置属性 -->
    <property name="name" value="mysql"/>
</bean>
  • 如果父Bean单纯只作为一个模板Bean来使用的话则可以将父Bean定位为抽象Bean(容器默认Bean为单例模式,因此在工厂创建的时候就会立即实例化Bean对象,而父Bean本身就不是一个完整的Bean,只是保留了部分数据的模板Bean,所以父Bean只能加载配置并不能直接实例化成对象。当定位为是一个abstract的Bean时,可以不提供class属性,并且ref和context中调用getBean方法均会报错。
  • 父Bean可以不需要明确的指定一个类,不过需要将父Bean定义为abstruct = true
<!-- 设置abstract为true后,容器将不会实例化Bean对象,但会保留配置属性 -->
<bean id="parentBean" abstract="true">
    <property name="name" value="msyql"/>
    <property name="password" value="123"/>
</bean>
  • 子Bean继承方式相同
<!-- 通过parent可以继承父bean的属性配置,同时也可以覆盖父bean的配置,子bean的类需要继承或包含父bean中所有的属性 -->
<bean id="sonBeanA" class="com.nobugnolife.bean.impl.SonBeanA" parent="parentBean">
    <property name="poolMax" value="100"/>
    <property name="timeout" value="1000"/>
    <property name="connectNum" value="30"/>
</bean>


<!-- spring提供的parent不只是可以通过继承,也可以是当前类所包含的属性,确保父Bean中有的属性,子Bean对应的类也有,注意是类,不是bean -->
<bean id="sonBeanB" class="com.nobugnolife.bean.impl.SonBeanB" parent="parentBean">
    <property name="tools" value="rock and stone"/>
    <!-- 同样也可以覆盖父bean中的属性,如果对应类而不是Bean是非继承关系的话,需要确保类中有相同的属性 -->
    <property name="name" value="MongoDB"/>
</bean>
  • 测试继承配置结果
@Test
public void testSonBean(){
    ApplicationContext ctx = new ClassPathXmlApplicationContext("parentBean.xml");
    SonBeanB sonBeanB = ctx.getBean("sonBeanB",SonBeanB.class);
    SonBeanA sonBeanA = ctx.getBean("sonBeanA",SonBeanA.class);
    SonBeanA sonBeanA02 = ctx.getBean("sonBeanA02",SonBeanA.class);
    System.out.println(sonBeanA);
    System.out.println(sonBeanB);
    System.out.println(sonBeanA02);
}
  • 输出结果

test_out


这里如果被定义为一个抽象Bean的话因为不需要关联class,所以完全可以理解为是单纯的对子Bean提前加载的BeanDefinition,可以不依托父类载体,而是直接从子类中提取的属性配置

  • 这边直接重新定义一个抽象parentBean,里面有Properties和int类型的uuid属性,并且只提供子Bean的定义类class。
public class ChildBean {
    private int uuid;

    private Properties props;

    public void setUuid(int uuid) {
        this.uuid = uuid;
    }

    @Override
    public String toString() {
        return "ChildBean{" +
                "uuid=" + uuid +
                ", props=" + props +
                '}';
    }

    public void setProps(Properties props) {
        this.props = props;
    }

}
<bean id="parentBean03" abstract="true">
    <property name="uuid" value="123"/>
    <property name="props">
        <props>
            <prop key="username">administrator</prop>
            <prop key="password">admin</prop>
        </props>
    </property>
</bean>
<bean id="childBean" class="com.nobugnolife.bean.impl.ChildBean" parent="parentBean03">
    <property name="props">
        <!-- 子集合重写密码并新增email配置 -->
        <props>
            <prop key="password">123</prop>
            <prop key="email">example@gmail.com</prop>
        </props>
    </property>
</bean>

test_child

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值