详解Spring Bean 之间的特殊关系

 更新时间:2018年05月05日 16:25:15   作者:deniro  
在 Spring 容器中,两个 Bean 之间除了通过 <ref> 建立依赖关系外,还存在着一些特殊关系。这篇文章给大家想想介绍了Spring Bean 之间的特殊关系,非常不错,具有参考借鉴价值,需要的朋友参考下

 在 Spring 容器中,两个 Bean 之间除了通过 <ref> 建立依赖关系外,还存在着一些特殊关系。

1 继承

在面向对象的编程原理中,当多个类拥有相同的方法和属性时,则可以引入父类用于消除重复的代码 。 而在 Spring 容器中,如果多个 Bean 存在相同的配置信息,我们可以定义一个父 Bean ,这样子 Bean 将会自动继承父 Bean 的配置信息 。

<!-- 父 Bean-->
<bean id="abstractBook" class="net.deniro.spring4.bean.Book"
   p:name="面纱" abstract="true">
</bean>
<!-- 子 Bean-->
<bean id="book1" class="net.deniro.spring4.bean.Book"
   p:press="重庆出版社" parent="abstractBook"/>
<bean id="book2" class="net.deniro.spring4.bean.Book"
   p:press="上海译文出版社" parent="abstractBook"/>

一般情况下,父 Bean 的功能是简化子 Bean 的配置,所以设置为抽象类(abstract="true");如果这里没有把父 Bean 设置为抽象类,那么 Spring 容器会实例化父 Bean 。

2 前置依赖

一般情况下,使用 <ref> 来建立 Bean 之间的依赖关系, Spring 容器负责管理这些关系,当实例化一个 Bean 时,容器保证该 Bean 所依赖的 Bean 都已经完成了初始化工作。

但在某些情况下,Bean 之间的依赖关系并没有那么明显。

假设这样一种场景,某系统设置了一些系统参数(如密码有效期、是否开启监控等),这些启动参数用来控制系统的运行逻辑,我们使用一个 Setting 类来表示这些参数:

public class Settings {
  /**
   * 密码过期时间(单位:天)
   */
  public static int PASS_TIMEOUT = 30;
  /**
   * 是否开启监控
   */
  public static boolean IS_MONITOR = false;
}

在此,我们为这些参数设置了默认值。系统还有一个管理后台,管理员可以通过这个后台调整这些系统参数并保存到数据库中。所以应用启动时,需要从数据库中加载这些系统参数:

public class System {
  public System() {
    init();
  }
  /**
   * 初始化
   */
  private void init() {
    //假设这些值来源于数据库
    Settings.PASS_TIMEOUT = 20;
    Settings.IS_MONITOR = true;
  }
}

系统有一个密码过期管理器,它会根据系统参数中的【密码过期的天数】,来创建检测密码是否过期的定时任务:

public class PassManager {
  int timeout;
  public PassManager() {
    timeout = Settings.PASS_TIMEOUT;
    timerTask();
  }
  /**
   * 检测密码是否过期的定时任务
   */
  private void timerTask() {
  }
  public int getTimeout() {
    return timeout;
  }
}

虽然 PassManager 并没有直接依赖于 Settings,但从逻辑上来看,PassManager 希望 System 加载初始化系统参数后再启动。

Spring 中可以通过 depends-on 属性显式地指定 Bean 的前置依赖 Bean, 保证这个 Bean 在实例化之前,它的前置依赖 Bean 已经加载完毕。

<bean id="system" class="net.deniro.spring4.bean.System"/>
<bean id="manager" class="net.deniro.spring4.bean.PassManager"
   depends-on="system"/>

如果前置依赖于多个 Bean ,那么可以通过逗号、空格或分号的方式来配置 Bean 名称 。

3 引用 ID

假设一个 Bean 需要引用另一个 Bean 的 id 值(beanName),这一般用于在运行期间在 Bean 中通过 getBean(beanName) 方法获取另一个 Bean 的情境。

可以这样配置:

<bean id="author" class="net.deniro.spring4.bean.Author"/>
<bean id="book" class="net.deniro.spring4.bean.Book"
   p:authorId="author"/>

Book 中新增 authorId 属性:

/**
 * author Bean 的 ID
 */
private String authorId;

虽然可以以这种字面值的形式进行设置,但两者之间并没有建立真正的引用关系。所以只有等到具体调用时才会发现配置错误。

Spring 提供了 <idref> 元素标签,通过 <idref> 引用另一个 Bean 的名称,这样在容器启动时,就会检查引用关系的正确性,可以提前发现错误的配置信息。

<bean id="author10" class="net.deniro.spring4.bean.Author"/>
<bean id="book10" class="net.deniro.spring4.bean.Book"
    >
  <property name="authorId">
    <idref bean="author10"/>
  </property>
</bean>

如果配置发生错误,Spring 容器启动时就会抛出 BeanDefinitionStoreException,而且 IDE 的XML 分析器也会提前发现引用错误,所以推荐使用 <idref> 元素标签的方式来引用 ID。

 总结

以上所述是小编给大家介绍的Spring Bean 之间的特殊关系,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

相关文章

  • java项目导出为.exe执行文件的方法步骤

    java项目导出为.exe执行文件的方法步骤

    最近做了个项目,想要转换成可执行文件,那么java项目如何导出为.exe执行文件,本文就介绍一下,主要使用jar2exe软件,感兴趣的可以了解一下
    2021-05-05
  • java拓展集合工具类CollectionUtils

    java拓展集合工具类CollectionUtils

    这篇文章主要为大家详细介绍了java拓展集合工具类CollectionUtils,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • java stream使用指南之sorted使用及进阶方式

    java stream使用指南之sorted使用及进阶方式

    这篇文章主要介绍了java stream使用指南之sorted使用及进阶方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • java中stack(栈)的使用代码实例

    java中stack(栈)的使用代码实例

    这篇文章主要介绍了java中stack(栈)的使用代码实例,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • JDBC中Statement和Preparement的使用讲解

    JDBC中Statement和Preparement的使用讲解

    今天小编就为大家分享一篇关于JDBC中Statement和Preparement的使用讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • Spring Boot项目完美大一统(结果异常日志统一)

    Spring Boot项目完美大一统(结果异常日志统一)

    这篇文章主要为大家介绍了Spring Boot项目完美大一统(结果异常日志统一)的实详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • spring项目实现单元测试过程解析

    spring项目实现单元测试过程解析

    这篇文章主要介绍了spring项目实现单元测试过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • Java字符串拼接的优雅方式实例详解

    Java字符串拼接的优雅方式实例详解

    字符串拼接一般使用“+”,但是“+”不能满足大批量数据的处理,下面这篇文章主要给大家介绍了关于Java字符串拼接的几种优雅方式,需要的朋友可以参考下
    2021-07-07
  • Java中的WeakHashMap源码分析

    Java中的WeakHashMap源码分析

    这篇文章主要介绍了Java中的WeakHashMap源码分析,WeakHashMap可能平时使用的频率并不高,但是你可能听过WeakHashMap会进行自动回收吧,下面就对其原理进行分析,需要的朋友可以参考下
    2023-09-09
  • Maven 多模块父子工程的实现(含Spring Boot示例)

    Maven 多模块父子工程的实现(含Spring Boot示例)

    这篇文章主要介绍了Maven 多模块父子工程的实现(含Spring Boot示例),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04

最新评论