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

发布时间 - 2026-01-11 03:24:02    点击率:

我们在应用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的继承与抽象代码示例的内容就到这里,希望对大家有所帮助。有兴趣的朋友可以参阅本站其他专题,精彩不断。感谢大家对本站的支持!


# spring  # bean  # 继承  # 抽象类  # 详解Spring 中如何控制2个bean中的初始化顺序  # Spring @Bean vs @Service注解区别  # 详解Spring简单容器中的Bean基本加载过程  # Spring Boot如何动态创建Bean示例代码  # 详解Spring中bean的几种注入方式  # Spring boot将配置属性注入到bean类中  # Java中Spring获取bean方法小结  # Spring中如何动态注入Bean实例教程  # Spring多种加载Bean方式解析  # Spring实战之抽象Bean和子Bean定义与用法示例  # 配置文件  # 主程序  # 子类  # 是个  # 为父  # 也可  # 这个时候  # 可以看出  # 真快  # 增加了  # 是一个  # 也不  # 是一种  # 不需要  # 就不  # 已有  # 是指  # 不可以  # 中有 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Midjourney怎样加参数调细节_Midjourney参数调整技巧【指南】  Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】  Laravel怎么实现验证码(Captcha)功能  如何在万网ECS上快速搭建专属网站?  Python自然语言搜索引擎项目教程_倒排索引查询优化案例  Linux网络带宽限制_tc配置实践解析【教程】  Laravel的路由模型绑定怎么用_Laravel Route Model Binding简化控制器逻辑  Laravel任务队列怎么用_Laravel Queues异步处理任务提升应用性能  制作公司内部网站有哪些,内网如何建网站?  西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?  Python结构化数据采集_字段抽取解析【教程】  网站建设整体流程解析,建站其实很容易!  作用域操作符会触发自动加载吗_php类自动加载机制与::调用【教程】  JavaScript常见的五种数组去重的方式  微信小程序 五星评分(包括半颗星评分)实例代码  Zeus浏览器网页版官网入口 宙斯浏览器官网在线通道  详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)  Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层  Laravel如何配置和使用缓存?(Redis代码示例)  如何在Windows 2008云服务器安全搭建网站?  Laravel项目结构怎么组织_大型Laravel应用的最佳目录结构实践  Laravel如何设置定时任务(Cron Job)_Laravel调度器与任务计划配置  宙斯浏览器视频悬浮窗怎么开启 边看视频边操作其他应用教程  Laravel怎么清理缓存_Laravel optimize clear命令详解  Laravel策略(Policy)如何控制权限_Laravel Gates与Policies实现用户授权  制作电商网页,电商供应链怎么做?  Laravel如何发送系统通知?(Notification渠道示例)  制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?  如何在沈阳梯子盘古建站优化SEO排名与功能模块?  开心动漫网站制作软件下载,十分开心动画为何停播?  Python面向对象测试方法_mock解析【教程】  HTML5打空格有哪些误区_新手常犯的空格使用错误【技巧】  javascript基本数据类型及类型检测常用方法小结  如何用花生壳三步快速搭建专属网站?  Laravel怎么实现验证码功能_Laravel集成验证码库防止机器人注册  如何用y主机助手快速搭建网站?  魔毅自助建站系统:模板定制与SEO优化一键生成指南  Laravel怎么设置路由分组Prefix_Laravel多级路由嵌套与命名空间隔离【步骤】  移动端脚本框架Hammer.js  谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复  如何注册花生壳免费域名并搭建个人网站?  Laravel中的Facade(门面)到底是什么原理  韩国服务器如何优化跨境访问实现高效连接?  专业商城网站制作公司有哪些,pi商城官网是哪个?  iOS UIView常见属性方法小结  Midjourney怎么调整光影效果_Midjourney光影调整方法【指南】  如何破解联通资金短缺导致的基站建设难题?  儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?  如何用西部建站助手快速创建专业网站?  DeepSeek是免费使用的吗 DeepSeek收费模式与Pro版本功能详解