详解Spring Bean 之间的特殊关系

作者:deniro 时间:2022-10-25 21:12:17 

 在 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 之间的特殊关系,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

来源:https://www.jianshu.com/p/e283906af3a9

标签:spring,bean,特殊关系
0
投稿

猜你喜欢

  • android使用handlerthread创建线程示例

    2023-07-05 17:29:57
  • C#中几个未知的Visual Studio编码技巧分享

    2022-09-16 04:21:19
  • 常用类之TCP连接类-socket编程

    2021-08-03 16:46:25
  • 23种设计模式(14)java迭代器模式

    2021-12-12 15:28:49
  • 基于Freemarker和xml实现Java导出word

    2022-07-11 23:15:12
  • Java JVM字节码指令集总结整理与介绍

    2021-09-18 17:10:20
  • SpringBoot浅析安全管理之OAuth2框架

    2022-10-12 17:17:04
  • Java编程实现打印螺旋矩阵实例代码

    2021-10-16 19:15:14
  • go语言题解LeetCode88合并两个有序数组示例

    2023-10-23 00:55:10
  • 简单探索 Java 中的惰性计算

    2023-11-16 20:25:28
  • java 中基本算法之希尔排序的实例详解

    2023-07-30 12:26:37
  • 如何解决修改StaticText的字体

    2023-05-25 08:40:14
  • 简述Java编程之关系操作符

    2021-08-07 09:44:23
  • idea生成类注释和方法注释的正确方法(推荐)

    2022-09-11 03:45:14
  • C#微信公众号开发之接收事件推送与消息排重的方法

    2022-01-31 08:44:46
  • Android ListView实现仿iPhone实现左滑删除按钮的简单实例

    2023-06-15 04:25:59
  • Android DialogUtils弹出窗工具类详解

    2022-05-13 17:34:56
  • Windows下使用Graalvm将Springboot应用编译成exe大大提高启动和运行效率(推荐)

    2023-09-27 02:05:02
  • Kotlin协程Job生命周期结构化并发详解

    2023-05-23 10:08:17
  • Java for循环标签跳转到指定位置的示例详解

    2022-10-04 17:52:31
  • asp之家 软件编程 m.aspxhome.com