跳转至

Spring Bean 继承

1. 介绍

  Spring允许继承bean的配置,被继承的bean称为父bean,继承这个父bean的bean称为子bean。子bean从父bean中继承配置,包括bean的属性配置,也可以覆盖从父bean继承过来的配置,父bean可以作为配置模板,也可以作为bean实例,若只想把父bean作为模板,可以设置的abstract属性为true,这样Spring将不会实例化这个bean。并不是元素里的所有属性都会被继承。比如:autowire,abstract等,也可以忽略父bean的class属性,让子bean指定自己的类,而共享相同的属性配置,但此时abstract必须设为true。

  bean 定义可以包含很多的配置信息,包括构造函数的参数,属性值,容器的具体信息例如初始化方法,静态工厂方法名,等等。

  子 bean 的定义继承父定义的配置数据。子定义可以根据需要重写一些值,或者添加其他值。

  Spring Bean 定义的继承与 Java 类的继承无关,但是继承的概念是一样的。你可以定义一个父 bean 的定义作为模板和其他子 bean 就可以从父 bean 中继承所需的配置。

  当你使用基于 XML 的配置元数据时,通过使用父属性,指定父 bean 作为该属性的值来表明子 bean 的定义。

2. 操作步骤

Nperson.class

package com.cmz.bean;

import java.util.*;

/**
 * @author summer
 * @create 2020-02-22 20:58
 */
public class Nperson{
    private int id;
    private String name;
    private Integer age;
    private String gender;
    private Date date;
    private String[] hobbies;
    private Address address;

    private List<Address> lists;
    private Set<String> sets;
    private Map<String,Object> maps;
    private Properties properties;

    public Nperson() {
        System.out.println("Nperson 被创建");
    }

    public Nperson(int id, String name, Integer age, String gender, Date date, String[] hobbies, Address address, List<Address> lists, Set<String> sets, Map<String, Object> maps, Properties properties) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.date = date;
        this.hobbies = hobbies;
        this.address = address;
        this.lists = lists;
        this.sets = sets;
        this.maps = maps;
        this.properties = properties;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String[] getHobbies() {
        return hobbies;
    }

    public void setHobbies(String[] hobbies) {
        this.hobbies = hobbies;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public List<Address> getLists() {
        return lists;
    }

    public void setLists(List<Address> lists) {
        this.lists = lists;
    }

    public Set<String> getSets() {
        return sets;
    }

    public void setSets(Set<String> sets) {
        this.sets = sets;
    }

    public Map<String, Object> getMaps() {
        return maps;
    }

    public void setMaps(Map<String, Object> maps) {
        this.maps = maps;
    }

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", date=" + date +
                ", hobbies=" + Arrays.toString(hobbies) +
                ", address=" + address +
                ", lists=" + lists +
                ", sets=" + sets +
                ", maps=" + maps +
                ", properties=" + properties +
                '}';
    }
}

ioc1.xml

<!--bean之间的继承关系-->
<!--可以使用abstract标签定义抽象bean,无法进行实例化【abstract="true"】-->
<bean id="parent" class="com.cmz.bean.Nperson" abstract="false">
    <property name="id" value="1"></property>
    <property name="name" value="张三"></property>
    <property name="age" value="20"></property>
    <property name="gender" value="男"></property>
    <property name="date" value="2020/02/28"></property>
</bean>
<!--可以通过parent属性来获取父bean中的某些属性值-->
<bean id="son" class="com.cmz.bean.Nperson" parent="parent">
    <property name="name" value="儿子"></property>
</bean>

抽象bean,在下面代码中建了一个id为parent的抽象类,设置abstract属性为false。若只想把父bean作为模板,可以将abstract改为true。

MyTest1.class

import com.cmz.bean.Nperson;
import com.cmz.bean.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author summer
 * @create 2020-02-22 21:06
 */
public class MyTest1 {
    public static void main(String[] args) {
        //继承
        ApplicationContext context_son = new ClassPathXmlApplicationContext("ioc1.xml");
        Nperson son = context_son.getBean("son", Nperson.class);
        System.out.println("son = "+son);

        ApplicationContext context_parent = new ClassPathXmlApplicationContext("ioc1.xml");
        Nperson parent = context_parent.getBean("parent", Nperson.class);
        System.out.println("parent = "+parent);
    }
}

输出

son = Person{id=1, name='儿子', age=20, gender='男', date=Fri Feb 28 00:00:00 CST 2020, hobbies=null, address=null, lists=null, sets=null, maps=null, properties=null}

parent = Person{id=1, name='张三', age=20, gender='男', date=Fri Feb 28 00:00:00 CST 2020, hobbies=null, address=null, lists=null, sets=null, maps=null, properties=null}

son继承parent。父 bean 自身不能被实例化,因为它是不完整的,而且它也被明确地标记为抽象的。当一个定义是抽象的,它仅仅作为一个纯粹的模板 bean 定义来使用的,充当子定义的父定义使用。