所有抽象Bean,就是指定 abstract 属性为true 的Bean,抽象Bean不能被实例化,Spring容器不会创建Bean的实例。抽象Bean的价值在于被继承,抽象Bean通常作为父Bean被继承。抽象Bean因为不能实例化,因此,既不能通过getBean() 显式地获得抽象Bean实例,也不能将抽象Bean注入成其他Bean依赖属性,在配置文件中也可以没有class属性。
子Bean定义可以从父Bean继承实现类、构造器参数、属性值等配置信息,无法继承如下属性:depends-on、autowire、singleton、scope、lazy-init。当子Bean指定的配置信息与父Bean模板所指定的配置信息不一致时,子Bean所指定的配置信息将会覆盖父Bean所指定的配置信息。在配置文件中如果父Bean定义中有class属性,则子Bean定义中可省略class属性,子Bean将采用与父Bean相同的实现类;如果父Bean定义中没有class属性,则子Bean定义中必须指定class属性,否则出错。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd"
>
<bean id="stoneAxe" class="DependencyInjection.StoneAxe"/>
<bean id="steelAxe" class="DependencyInjection.SteelAxe"/>
<!-- 抽象、继承 -->
<bean id="chineseTemplate" class="DependencyInjection.Chinese" abstract="true">
<property name="axe" ref="steelAxe"/>
</bean>
<bean id="chineseInherit" parent="chineseTemplate">
<property name="axe" ref="stoneAxe"/> <!-- 覆盖父Bean的中依赖关系的配置-->
</bean>
</beans>
package UnderstandingBeanInContainer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import DependencyInjection.Person;
public class Test {
public static void main(String[] args) {
ApplicationContext ctx =
new ClassPathXmlApplicationContext("bean.xml");
Person p = ctx.getBean("chineseInherit",Person.class);
p.useAxe();
}
}
Spring中的Bean继承与Java中的继承截然不同。前者是实例与实例之间的参数的延续,后者则是一般到特殊的细化;前者是对象与对象之间的关系,后者是类与类之间的关系。
区别:
>> Spring中的子Bean和父Bean可以是不同的类型,但Java中的继承则可保证子类是一种特殊的父类。
>> Spring中的Bean继承是实例之间的关系,因此主要表现为参数值的延续;而Java中的继承是类之间的关系,主要表现为方法、属性的延续。
>> Spring中的子Bean不可作为父Bean使用,不具备多态性;Java中的子类实例完全可当成父类实例使用。