《Spring攻略(第2版)》——1.5 指定Bean引用

简介: 如果Bean实例只用于一个特殊的属性,可以声明为内部Bean。内部Bean声明直接包含在或中,不设置任何id或者name属性。这样,这个Bean将是匿名的,无法在别处使用。实际上,即使为内部Bean定义id或者name属性,也将被忽略。

本节书摘来自异步社区《Spring攻略(第2版)》一书中的第1章,第1.5节,作者: 【美】Gary Mak , Josh Long , Daniel Rubio著,更多章节内容可以访问云栖社区“异步社区”公众号查看

1.5 指定Bean引用

1.5.1 问题
组成应用程序的Bean往往需要互相协作完成应用功能。为了Bean之间的相互访问,你必须在Bean配置文件中指定Bean引用。

1.5.2 解决方案
在Bean配置文件中,你可以用元素为Bean属性或者构造程序参数指定Bean引用。只需要用元素指定一个简单值就可以轻松完成这一工作。你也可以像内部Bean一样直接地在属性或者构造程序中包含一个Bean声明。

1.5.3 工作原理
在你的序列生成器中接受字符串值作为前缀的灵活性不足以满足将来的要求。如果前缀生成可以由某种编程逻辑自定义将会更好。你可以创建PrefixGenerator接口来定义前缀生成操作。

package com.apress.springrecipes.sequence;

public interface PrefixGenerator {

   public String getPrefix();
}

使用特殊的模式格式化当前系统日期是一种前缀生成策略。让我们创建实现PrefixGenerator接口的DatePrefixGenerator类。

package com.apress.springrecipes.sequence;
...
public class DatePrefixGenerator implements PrefixGenerator {
   private DateFormat formatter;

   public void setPattern(String pattern) {
     this.formatter = new SimpleDateFormat(pattern);
   }

   public String getPrefix() {
     return formatter.format(new Date());
   }
}

这个生成器的模式将通过设值方法setPattern()注入,然后用于创建java.text.DateFormat对象格式化日期。由于模式字符串在DateFormat对象创建之后不再使用,所以没有必要将它存入一个私有字段中。

现在你可以用任意模式字符串声明类型为DatePrefixGenerator的Bean来格式化日期。

<bean id="datePrefixGenerator"
   class="com.apress.springrecipes.sequence.DatePrefixGenerator">
   <property name="pattern" value="yyyyMMdd" />
</bean>

为设值方法指定Bean引用
为了应用这个前缀生成器方法,SequenceGenerator类应该接受PrefixGenerator类型的对象而不是简单的前缀字符串。你可以选择设置方法注入来接受这个前缀生成器。你必须删除可能导致编译错误的prefix属性,以及设值方法和构造程序。

package com.apress.springrecipes.sequence;

public class SequenceGenerator {
   ...
   private PrefixGenerator prefixGenerator;

   public void setPrefixGenerator(PrefixGenerator prefixGenerator) {
     this.prefixGenerator = prefixGenerator;
   }

   public synchronized String getSequence() {
     StringBuffer buffer = new StringBuffer();
     buffer.append(prefixGenerator.getPrefix());
     buffer.append(initial + counter++);
     buffer.append(suffix);
     return buffer.toString();
   }
}

然后,SequenceGenerator bean可以包含一个元素,引用datePrefixGenerator bean作为其prefixGenerator属性。

<bean id="sequenceGenerator"
   class="com.apress.springrecipes.sequence.SequenceGenerator">
   <property name="initial" value="100000" />
   <property name="suffix" value="A" />
   <property name="prefixGenerator">
     <ref bean="datePrefixGenerator" />
   </property>
</bean>

元素的bean属性中的Bean名称可以是对IoC容器中的任何Bean的引用,即使这个Bean不在同一个XML配置文件中定义。如果你引用相同XML文件中的一个Bean,应该使用local属性,因为这是一个XML ID引用。你的XML编辑器将帮助你校验Bean ID是否存在于相同的XML文件中(也就是引用完整性)。

<bean id="sequenceGenerator"
   class="com.apress.springrecipes.sequence.SequenceGenerator">
   ...
   <property name="prefixGenerator">
     <ref local="datePrefixGenerator" />
   </property>
</bean>

还有一个在元素的ref属性中指定Bean引用的方便简写。

<bean id="sequenceGenerator"
   class="com.apress.springrecipes.sequence.SequenceGenerator">
   ...
   <property name="prefixGenerator" ref="datePrefixGenerator" />
</bean>

但是这样一来,你的XML编辑器将不能校验引用完整性。实际上,这跟指定元素的bean属性效果相同。

Spring 2.x提供另一个便利的简写来指定Bean引用,使用pschema将bean引用作为元素的一个属性。这可以缩短XML配置行。

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:p="http://www.springframework.org/schema/p"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="sequenceGenerator"
     class="com.apress.springrecipes.sequence.SequenceGenerator"
     p:suffix="A" p:initial="1000000"
     p:prefixGenerator-ref="datePrefixGenerator" />
</beans>

为了区分Bean引用与简单的属性值,你必须在属性名后面加上-ref后缀。

为构造程序参数指定Bean引用
Bean引用也可以应用到构造程序注入。例如,你可以添加一个接受PrefixGenerator对象参数的构造程序。

package com.apress.springrecipes.sequence;

public class SequenceGenerator {
   ...
   private PrefixGenerator prefixGenerator;

   public SequenceGenerator(PrefixGenerator prefixGenerator) {
     this.prefixGenerator = prefixGenerator;
   }
}

在元素中,你可以用像在元素中一样包含一个Bean引用。

<bean id="sequenceGenerator"
   class="com.apress.springrecipes.sequence.SequenceGenerator">
   <constructor-arg>
     <ref local="datePrefixGenerator" />
   </constructor-arg>
   <property name="initial" value="100000" />
   <property name="suffix" value="A" />
</bean>

指定Bean引用的简写也适用于。

<bean id="sequenceGenerator"
   class="com.apress.springrecipes.sequence.SequenceGenerator">
   <constructor-arg ref="datePrefixGenerator" />
   ...
</bean>

声明内部Bean
如果Bean实例只用于一个特殊的属性,可以声明为内部Bean。内部Bean声明直接包含在或中,不设置任何id或者name属性。这样,这个Bean将是匿名的,无法在别处使用。实际上,即使为内部Bean定义id或者name属性,也将被忽略。

<bean id="sequenceGenerator"
   class="com.apress.springrecipes.sequence.SequenceGenerator">
   <property name="initial" value="100000" />
   <property name="suffix" value="A" /
   <property name="prefixGenerator">
     <bean class="com.apress.springrecipes.sequence.DatePrefixGenerator">
        <property name="pattern" value="yyyyMMdd" />
     </bean>
   </property>
</bean>

内部Bean也可以在构造程序参数中声明。

<bean id="sequenceGenerator"
   class="com.apress.springrecipes.sequence.SequenceGenerator">
   <constructor-arg>
     <bean class="com.apress.springrecipes.sequence.DatePrefixGenerator">
        <property name="pattern" value="yyyyMMdd" />
     </bean>
   </constructor-arg>
   <property name="initial" value="100000" />
   <property name="suffix" value="A" />
</bean>
相关文章
|
9天前
|
Java uml Spring
手写spring第四章-完善bean实例化,自动填充成员属性
手写spring第四章-完善bean实例化,自动填充成员属性
17 0
|
26天前
|
Java 应用服务中间件 Spring
Spring系列文章:Bean的作⽤域
Spring系列文章:Bean的作⽤域
|
26天前
|
Java Spring 容器
Spring系列文章:Bean的获取⽅式
Spring系列文章:Bean的获取⽅式
|
1月前
|
缓存 Java Spring
Spring 框架中 Bean 的生命周期
Spring 框架中 Bean 的生命周期
35 1
|
2月前
|
XML Java 开发者
Spring Boot中的bean注入方式和原理
Spring Boot中的bean注入方式和原理
83 0
|
2月前
|
XML 缓存 Java
Spring源码之 Bean 的循环依赖
循环依赖是 Spring 中经典问题之一,那么到底什么是循环依赖?简单说就是对象之间相互引用, 如下图所示: 代码层面上很好理解,在 bean 创建过程中 class A 和 class B 又经历了怎样的过程呢? 可以看出形成了一个闭环,如果想解决这个问题,那么在属性填充时要保证不二次创建 A对象 的步骤,也就是必须保证从容器中能够直接获取到 B。 一、复现循环依赖问题 Spring 中默认允许循环依赖的存在,但在 Spring Boot 2.6.x 版本开始默认禁用了循环依赖 1. 基于xml复现循环依赖 定义实体 Bean java复制代码public class A {
|
5天前
|
消息中间件 安全 Java
在Spring Bean中,如何通过Java配置类定义Bean?
【4月更文挑战第30天】在Spring Bean中,如何通过Java配置类定义Bean?
14 1
|
8天前
|
前端开发 Java 数据格式
【Spring系列笔记】定义Bean的方式
在Spring Boot应用程序中,定义Bean是非常常见的操作,它是构建应用程序的基础。Spring Boot提供了多种方式来定义Bean,每种方式都有其适用的场景和优势。
23 2
|
9天前
|
XML Java 数据格式
手写spring第七章-完成便捷实现bean对象初始化和销毁方法
手写spring第七章-完成便捷实现bean对象初始化和销毁方法
6 0
|
9天前
|
XML Java 数据格式
手写spring第六章-实现应用上下文,完成bean的扩展机制
手写spring第六章-实现应用上下文,完成bean的扩展机制
14 0