Spring中bean的继承与抽象代码示例

我们在应用Spring时,在一般的设计时,肯定要用的抽象类。那在Spring中怎么样配置这些抽象Bean呢。请看下面:

如果两个bean 之间的配置信息非常相似,可利用继承来减少重复配置工作。

继承是指子bean 定义可从父bean 定义继承部分配置信息,也可覆盖特定的配置信息,或者添加一些配置。使用继承配置可以节省很多的配置工作。在实际应用中,通用配置会被配置成模板,可供子bean 继承。

使用abstract 属性

正如前面所介绍的,通用的配置会被配置成模板,而模板不需要实例化,仅仅作为子bean 定义的模板使用。而ApplicationContext 默认预初始化所有的singleton bean 。使用abstract 属性,可以阻止模板bean 被预初始化。abstract 属性为true 的bean 称为抽象bean ,容器会忽略所有的抽象bean 定义,预初始化时不初始化抽象bean。如果没有定义abstract 属性,该属性默认为false 。如下配置文件定义了一个抽象bean ,该抽象bean 作为模板使用:

public class SteelAxe implements Axe
{
//count 是个状态值,每次执行chop 方法该值增加1
private int count = 0;
public SteelAxe(){
System.out.println("Spring实例化依赖bean: SteelAxe 实例.. .");
}
//测试用方法
public String chop(){
return "钢斧砍柴真快" + ++count;
}
}
public class Chinese implements Person
//面向Axe 接口编程,而不是具体的实现类
private Axe axe;
//默认的构造器
public Chinese(){
System.out.println("Spring实例化主调bean: Chinese 实例... ");
}
//设值注入所需的setter 方法
public void setAxe( Axe axe){
System.out.pr工ntln (" Spring 执行依赖关系注入...");
this.axe = axe;
}
//实现Person 接口的useAxe 方法
public void useAxe(){
System.out.println(axe.chop());
}
}
<?xml version="1.0" encoding="gb2312"?>
<!一指定Spring 配置文件的dtd>
<lDOCTYPE beans PUBL工C "-//SPRING//DTD BEAN//EN"
''http://www.springframework.org/dtd/spring-beans.dtd''>
<!一Spring 配置文件的根元素一〉
<beans>
<bean id="steelAxe" class="lee.SteelAxe"/>
<!… 通过abstract 属性定义该bean 是抽象bean-->
<bean id="chineseTemplate" class="lee.Chinese" abstract="true">
<!一定义依赖注入的属性一〉
<property name="axe">
<ref local="steelAxe"/>
</property>
</bean>
</beans>

从配置文件中可以看出,抽象bean 的定义与普通bean 的定义几乎没有区别,仅仅增加abstract 属性为true ,但主程序执行结果却有显著的差别。下面的主程序采用AppliactionContext 作为Spring 容器, AppliationContext 默认预初始化所有的singleton bean。其主程序部分如下:

public class BeanTest
{
public static void main(String[] args)throws Exception{
ApplicationContext ctx = new FileSysternXmlApplicationContext("bean.xml");
}
}
//主程序部分仅仅实例化了ApplicationContext,在实例化ApplicationContext时,默认实例化singleton bean。

程序执行结果如下:

Spring 实例化依赖bean: SteelAxe 实例.. .

容器并没有实例化chineseTemplate bean ,而忽略了所有声明为abstract 的beano 如果取消abstract 属性定义,则程序执行结果如下:

Spring 实例化依赖bean: SteelAxe 实~J...

Spring 实例化主调bean: Chinese 实例.. .

Spring 执行依赖关系注入...

可以看出,抽象bean 是一个bean 模板,容器会忽略抽象bean 定义,因而不会实例化抽象bean。但抽象bean 无须实例化,因此可以没有class 属性。如下的配置文件也有效:

<?xml version="1.0" e口coding="gb2312"?>
<!一指定Spring 配置文件的dtd>
<!DOCTYPE beans PUBLIC "-/!SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd''>
<! -- Spring 配置文件的根元素-->
<beans>
<bean id="steelAxe" class="lee.SteelAxe"/>
<!一通过abstract 属性定义该bean 是抽象bean,抽象bean 没有指定class 属性一〉
<bean id="chineseTemplate" abstract="true">
<!… 定义依赖注入的属性一〉
<property name="axe">
<ref local="steelAxe"/>
</property>
</bean〉
</beans>

注意:抽象bean 不能实例化,既不能通过getBean 获得抽象bean,也不能让其他bean 的ref 属性值指向抽象bean,因而只要企图实例化抽象bean,都将导致错误。

定义子bean

我们把指定了parent 属性值的bean 称为子bean; parent 指向子bean 的模板,称为父bean 。子bean 可以从父bean 继承实现类、构造器参数及属性值,也可以增加新的值。如果指定了init-method , destroy-method 和factory-method 的属性,则它们会覆盖父bean的定义。子bean 无法从父bean 继承如下属性: depends-on, autowire, dependency-check,singleton, lazy-init。这些属性将从子bean 定义中获得,或采用默认值。通过设置parent 属性来定义子bean , parent 属性值为父bean id。修改上面的配置文件如下,增加了子bean 定义:

<?xml version="1.0" encoding="gb2312"?>
<!一指定Spring 配置文件的dtd>
<lDOCTYPE beans PUBL工C "-//SPRING//DTD BEAN//EN"
''http://www.springframework.org/dtd/spring-beans.dtd''>
<!-- Spring 配置文件的根元素一〉
<beans>
<bean id="steelAxe" class="lee.SteelAxe"/>
<!一通过abstract 属性定义该bean 是抽象bean-->
<bean id="chineseTemplate" class="lee.Chinese" abstract="true">
<!-- 定义依赖注入的属性一〉
<property name="axe">
<ref local="steelAxe"/>
</property>
</bean>
<!一通过parent 属性定义子bean ?
<bean id="chinese" parent="chineseTemplate"/>
</beans>

子bean 与普通bean 的定义并没有太大区别,仅仅增加了parent 属性。子bean 可以没有class 属性,若父bean 定义中有class 属性,则子bean 定义中可省略其class 属性,但子bean 将采用与父bean 相同的实现类。

测试程序修改如下:

public class BeanTest
{
public static void main(String[] args)throws Exception{
ApplicationContext ctx = new FileSysternXmlApplicationContext("bean.xml");
Person p = (Person)ctx.getBean("chinese");
p.useAxe();
}
}

程序执行结果如下:

Spring 实例化依赖bean: Stee1Axe 实例.. .

Spring实例化主调bean: Chinese 实例.. .

spring 执行依赖关系注入...

钢斧砍柴真快

另外,子bean 从父bean 定义继承了实现类并依赖bean 。但子bean 也可覆盖父bean的定义,看如下的配置文件:

//Axe 的实现类StoneAxe如下:
public class StoneAxe implements Axe
//默认构造器
public StoneAxe(){
System.out.println("Spring实例化依赖bean: StoneAxe实例.. .");
}
//实现Axe 接口的chop 方法
public String chop(){
return "石斧砍柴好慢";
}
}

Chinese子类如下:

public class Shanghai extends Chinese {

  public void show() {
        System.out.println("子Bean ,中国的上海");
  }

}
<?xm1 version="1.0" encoding="gb2312"?>
<! 指定Spring 配置文件的dtd>
<lDOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
''http://www.springframework.org/dtd/spring-beans.dtd''>
<! -- Spring 配置文件的根元素一〉
<beans>
<bean id="steelAxe" class="lee.SteelAxe"/>
<bean id="stoneAxe" class="lee.StoneAxe"/>
<!一通过abstract 属性定义该bean 是抽象bean-->
<bean id="chineseTemplate" class="lee.Chinese" abstract="true">
<property name="axe">
<ref local="steelAxe"/>
</property>
</bean>
<!一通过parent 属性定义子bean-->
<bean id="shanghai" parent="chineseTemplate">
<!一覆盖父bean 的依赖定义…〉
<property name="axe">
<ref local="stoneAxe"/>
</property>
</bean>
</beans>

此时,子bean 的依赖不再是父bean 定义的依赖了。注意,这个时候的父类lee.Chinese 不能是抽象类,(说明下:有abstract="true")不一定说明这个类一定是个抽象类,不是抽象类同样可以在Spring里定义为抽象Bean,如果你的Class是抽象类,那这个时候就不能用父Bean的Class,一定要在子Bean中定义Class来初始化这个子Bean)

测试程序修改如下:

public class BeanTest
{
public static void main(String[] args)throws Exception{
ApplicationContext ctx = new FileSysternXmlApplicationContext("bean.xml");
Person p = (Person)ctx.getBean("shanghai");
p.useAxe();
}
}

按上面的测试程序执行结果如下:

Spring 实例化依赖bean: SteelAxe 实例.. .

spring 实例化依赖bean: StoneAxe 实例.. .

Spring 实例化主调bean: Chinese 实例.. .

Spring 执行依赖关系注入...

石斧砍柴好慢

注意:上例中的子bean 定义都没有class 属性,因为父bean 定义中已有class 属性,子bean 的class 属性可从父bean 定义中继承,但需要注意的是从父Bean继承Class时,父Bean一定不能是抽象类,因为抽象类不能创建实例;如果父bean 定义中也没有指定class 属性,则子bean 定义中必须指定class 属性,否则会出错;如果父bean 定义指定了class 属性,子bean 定义也指定了class 属性,则子bean 将定义的class 属性覆盖父bean 定义的class属性。

Spring 中bean的继承和Java中的继承截然不同,前者是实例与实例之间的参数的延续,后者是一般到特殊的细化,前者是对象和对象之间的关系,后者是类和类之间的关系。

a.Spring中的子bean和父bean可以是不同的类型,但是Java中的继承,子类是一种特殊的父类;

b.Spring中的bean的继承是实例之间的关系,主要表现在参数的延续,而Java中的继承是类与类之间的关系,主要体现在方法和属性的延续。

c.Spring中子bean不可以作为父bean使用,不具备多态性,Java中的子类实例完全可以当作父类实例使用。

总结

本文有关Spring中bean的继承与抽象代码示例的内容就到这里,希望对大家有所帮助。有兴趣的朋友可以参阅本站其他专题,精彩不断。感谢大家对本站的支持!

(0)

相关推荐

  • Java的Spring框架中bean的继承与内部bean的注入

    bean的定义继承 bean定义可以包含很多的配置信息,包括构造函数的参数,属性值,比如初始化方法,静态工厂方法名等容器的具体信息. 子bean定义从父定义继承配置数据.子的定义可以覆盖一些值,或者根据需要添加其他. Spring bean定义继承无关,与Java类的继承,但继承的概念是一样的.你可以定义一个父bean定义为模板和其他孩子bean可以从父bean继承所需的配置. 当使用基于XML的配置元数据,指明一个子bean定义使用所在的当前属性指定的父bean作为这个属性的值. 例如: 让我

  • Spring中bean的继承与抽象代码示例

    我们在应用Spring时,在一般的设计时,肯定要用的抽象类.那在Spring中怎么样配置这些抽象Bean呢.请看下面: 如果两个bean 之间的配置信息非常相似,可利用继承来减少重复配置工作. 继承是指子bean 定义可从父bean 定义继承部分配置信息,也可覆盖特定的配置信息,或者添加一些配置.使用继承配置可以节省很多的配置工作.在实际应用中,通用配置会被配置成模板,可供子bean 继承. 使用abstract 属性 正如前面所介绍的,通用的配置会被配置成模板,而模板不需要实例化,仅仅作为子b

  • Spring实例化bean过程解析及完整代码示例

    提出问题 Spring中Bean的实例化是Bean生命周期的一个重要环节,通常Bean初始化后将不再改变. 那么Spring实例Bean的过程到底是怎么样的呢?! Spring实例化bean过程分析 要想获取到一个bean对象,得先通过BeanFactory的getBean()方法获取,期间会经过一系列步骤来实例化这个bean对象: 第一步:调用Bean的默认构造方法(当然也可以是指定的其它构造方法),生成bean实例:bean1. 第二步:检查Bean配置文件中是否注入了Bean的属性值,如果

  • Spring中Bean的命名方式代码详解

    本文主要描述的是关于spring中bean的命名方式,通过简单实例向大家介绍了六种方式,具体如下. 一般情况下,在配置一个Bean时需要为其指定一个id属性作为bean的名称.id在IoC容器中必须是唯一的,此外id的命名需要满足xml对id的命名规范. 在实际情况中,id命名约束并不会给我们带来影响.但是如果用户确实希望用到一些特殊字符来对bean进行命名,那么可以使用bean的name属性来进行命名,name属性没有字符上的限制,几乎可以使用任何字符. 每个Bean可以有一个或多个id,我们

  • 详解Spring中bean的几种注入方式

    首先,要学习Spring中的Bean的注入方式,就要先了解什么是依赖注入.依赖注入是指:让调用类对某一接口的实现类的实现类的依赖关系由第三方注入,以此来消除调用类对某一接口实现类的依赖. Spring容器中支持的依赖注入方式主要有属性注入.构造函数注入.工厂方法注入.接下来将为大家详细介绍这三种依赖注入的方式以及它们的具体配置方法. 1.属性注入 属性注入即通过setXXX( )方法注入bean的属性值或依赖对象.由于属性注入方式具有可选择性和灵活性高的特点,因此它也是实际开发中最常用的注入方式

  • Spring中Bean的加载与SpringBoot的初始化流程详解

    目录 前言 第一章 Spring中Bean的一些简单概念 1.1 SpingIOC简介 1.2 BeanFactory 1.2.1 BeanDefinition 1.2.2 BeanDefinitionRegistry 1.2.3 BeanFactory结构图 1.3 ApplicationContext 第二章 SpringBoot的初始化流程 2.1 准备阶段 2.2 运行阶段 2.2.1 监听器分析 2.2.2 refreshContext 2.3 总结 前言 一直对它们之间的关系感到好奇

  • 详解Spring 中 Bean 的生命周期

    前言 这其实是一道面试题,是我在面试百度的时候被问到的,当时没有答出来(因为自己真的很菜),后来在网上寻找答案,看到也是一头雾水,直到看到了<Spring in action>这本书,书上有对Bean声明周期的大致解释,但是没有代码分析,所以就自己上网寻找资料,一定要把这个Bean生命周期弄明白! ​ 网上大部分都是验证的Bean 在面试问的生命周期,其实查阅JDK还有一个完整的Bean生命周期,这同时也验证了书是具有片面性的,最fresh 的资料还是查阅原始JDK!!! 一.Bean 的完整

  • 浅谈Spring中Bean的作用域、生命周期

    本文主要探究的是关于Bean的作用域.生命周期的相关内容,具体如下. Bean的作用域 Spring 3中为Bean定义了5中作用域,分别为singleton(单例).prototype(原型).request.session和global session,5种作用域说明如下: 1.singleton:单例模式,Spring IoC容器中只会存在一个共享的Bean实例,无论有多少个Bean引用它,始终指向同一对象.Singleton作用域是Spring中的缺省作用域,也可以显示的将Bean定义为

  • spring中使用mybatis实现批量插入的示例代码

    有3种实现方式:foreach,spring事务,以及ExecutorType.BATCH. 1. foreach方式 这种方式实际是对SQL语句进行拼接,生成一个长长的SQL,对很多变量进行绑定.如果数据量不大(1000个以内),可以用这种方式.如果数据量太大,可能数据库会报错. 定义接口 public interface StudentMapper05 { public void insertStudent(List<Student> studentList); } 定义mapper 适用

  • Spring中bean的生命周期之getSingleton方法

    Spring中bean的生命周期 要想讲清楚spring中bean的生命周期,真的是不容易,以AnnotationConfigApplicationContext上下文为基础来讲解bean的生命周期,AnnotationConfigApplicationContext是基于注解的上下文,使用XML的方式现在很少见,所以以此上下文为基础,使用XML的上下文ClassPathXmlApplicationContext的步骤和AnnotationConfigApplicationContext类似.

  • 详解Spring中Bean的作用域与生命周期

    目录 一.Bean的作用域 二.Bean的生命周期 使用代码演示Bean的生命周期 一.Bean的作用域 通过Spring容器创建一个Bean的实例时,不仅可以完成Bean的实例化,还可以使用Bean的scope属性为bean设置作用域. 语法格式:<bean id="别名" scope="作用域" class="对应实现类"> 作用域的种类:(sing) singleton和prototype区别:(该两种比较常用) ① singl

随机推荐