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);
}
- 输出结果
这里如果被定义为一个抽象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>