《Spring攻略(第2版)》——1.11 用XML配置自动装配Bean

简介: 已经看到,如果Spring找到超过一个候选的自动装配Bean,将会抛出UnsatisfiedDependency Exception异常。另一方面,如果自动装配模式设置为byName或byType,而Spring无法找到匹配的Bean进行装配,将把该属性保持为未设置状态,这可能导致一个NullPointerException异常或者一个值没有初始化。

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

1.11 用XML配置自动装配Bean

1.11.1 问题
当一个Bean需要访问另一个Bean时,你可以显式指定引用装配它。但是,如果你的容器能够自动装配Bean,就可以免去手工配置装配的麻烦。

1.11.2 解决方案
Spring IoC容器能够帮助你自动装配Bean。你只要在的autowire属性中指定自动装配模式就可以了。表1-2列出了Spring支持的自动装配模式。
screenshot
*默认模式是no,但是可以设置根元素的default-autowire属性修改。这个默认模式将被Bean自己指定的模式覆盖。

尽管自动装配功能非常强大,但代价是降低了Bean配置的可读性。因为自动装配由Spring在运行时执行,你无法从Bean配置文件中得到Bean装配的方式。在实践中,我们建议仅将自动装配应用到组件依赖不复杂的应用程序中。

1.11.3 工作原理
按照类型的自动装配
你可以将sequenceGenerator bean的autowire属性设置为byType并且不设置prefixGenerator属性。然后,Spring将试图装配类型与PrefixGenerator兼容的Bean。在这个例子中,将自动装配datePrefixGenerator bean。

<beans ...>
   <bean id="sequenceGenerator"
     class="com.apress.springrecipes.sequence.SequenceGenerator"
     autowire="byType">
     <property name="initial" value="100000" />
     <property name="suffix" value="A" />
   </bean>

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

按照类型的自动装配的主要问题是有时候在IoC类型中具有超过一个与目标类型兼容的Bean。在这种情况下,Spring将无法确定哪个Bean最适合于该属性,从而无法进行自动装配。例如,如果你有另一个以当前年份作为前缀的前缀生成器,按照类型的自动装配将会立即被破坏。

<beans ...>
   <bean id="sequenceGenerator"
     class="com.apress.springrecipes.sequence.SequenceGenerator"
     autowire="byType">
     <property name="initial" value="100000" />
     <property name="suffix" value="A" />
   </bean>

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

   <bean id="yearPrefixGenerator"
     class="com.apress.springrecipes.sequence.DatePrefixGenerator">
     <property name="pattern" value="yyyy" />
   </bean>
</beans>

如果找到超过一个可供自动装配的Bean,Spring将会抛出一个UnsatisfiedDependency Exception异常。

Exception in thread "main"
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sequenceGenerator' defined in class path resource [beans.xml]: Unsatisfied dependency expressed through bean property 'prefixGenerator': No unique bean of type [com.apress.springrecipes.sequence.PrefixGenerator] is defined: expected single matching bean but found 2: [datePrefixGenerator, yearPrefixGenerator]

按照名称的自动装配
byName是另一种自动装配模式,有时候它能解决按照类型的自动装配的问题。它的工作方式与byType类似,但是这时候,Spring将试图装配一个类名与该属性名相同的Bean,而不是兼容的类型。因为Bean的name属性在一个容器中是唯一的,按照名称的自动装配不会导致歧义。

<beans ...>
   <bean id="sequenceGenerator"
     class="com.apress.springrecipes.sequence.SequenceGenerator"
     autowire="byName">
     <property name="initial" value="100000" />
     <property name="suffix" value="A" />
   </bean>

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

但是,按照名称的自动装配并不能工作于任何情况。有时候,你不可能使目标Bean的名称与属性相同。在实践中,你往往必须在保持其他依赖自动装配的同时明确地指定歧义的依赖。这意味着你混合了显式装配和自动装配。

按照构造程序的自动装配
constructor自动装配模式与byType的工作方式类似,但是更复杂一些。对于具有单个构造程序的Bean,Spring将试图为每个构造程序参数装配一个具有兼容类型的Bean。但是对于具有多个构造程序的Bean,这一过程就更加复杂。Spring首先试图为每个构造程序的每个参数找到一个类型兼容的Bean。然后,将选择具有最多匹配参数的构造程序。

假定SequenceGenerator有一个默认构造程序和一个具有参数PrefixGenerator的构造程序。

package com.apress.springenterpriserecipes.sequence;

public class SequenceGenerator {

   public SequenceGenerator() {}

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

在这种情况下,第二个构造程序匹配并且被选中,因为Spring可以找到一个类型与Prefix Generator兼容的Bean。

<beans ...>
   <bean id="sequenceGenerator"
     class="com.apress.springrecipes.sequence.SequenceGenerator"
     autowire="constructor">
     <property name="initial" value="100000" />
     <property name="suffix" value="A" />
   </bean>

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

但是,一个类中的多个构造程序可能造成构造程序参数匹配的歧义。如果你要求Spring确定一个构造程序,情况可能更加复杂。所以,如果你使用这种自动装配模型,就要非常小心地避免歧义。

自动检测的自动装配
自动装配模式autodetect要求Spring在byType和constructor模式中作出决定。如果至少找到一个没有参数的默认构造程序,将选择byType模式,否则,将选择constructor模式。因为SequenceGenerator类定义了默认的构造程序,将选择byType模式。这意味着前缀生成器将通过设值方法注入。

<beans ...>
   <bean id="sequenceGenerator"
     class="com.apress.springrecipes.sequence.SequenceGenerator"
     autowire="autodetect">
     <property name="initial" value="100000" />
     <property name="suffix" value="A" />
   </bean>

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

自动装配与依赖检查
你已经看到,如果Spring找到超过一个候选的自动装配Bean,将会抛出UnsatisfiedDependency Exception异常。另一方面,如果自动装配模式设置为byName或byType,而Spring无法找到匹配的Bean进行装配,将把该属性保持为未设置状态,这可能导致一个NullPointerException异常或者一个值没有初始化。但是,如果你希望在自动装配无法装配的Bean时得到通知,应该将dependency-check属性设置为objects或者all。

在这种情况下,如果自动装配无效将会抛出UnsatisfiedDependencyException异常。objects将通知Spring在相同的Bean工厂中无法找到协同Bean时发出一个错误。all通知容器在任何作为依赖的简单属性类型(String类型或者原始类型)未被设置时发出一个错误,这补充了objects的功能。

<bean id="sequenceGenerator"
   class="com.apress.springrecipes.sequence.SequenceGenerator"
   autowire="byName" dependency-check="objects">
   <property name="initial" value="100000" />
   <property name="suffix" value="A" />
</bean>
相关文章
|
1月前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
133 26
|
3月前
|
Java Spring
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
196 73
|
3月前
|
XML Java 数据格式
【SpringFramework】Spring IoC-基于XML的实现
本文主要讲解SpringFramework中IoC和DI相关概念,及基于XML的实现方式。
123 69
|
2月前
|
监控 Java 数据库连接
Spring c3p0配置详解
在Spring项目中配置C3P0数据源,可以显著提高数据库连接的效率和应用程序的性能。通过合理的配置和优化,可以充分发挥C3P0的优势,满足不同应用场景的需求。希望本文的详解和示例代码能为开发者提供清晰的指导,帮助实现高效的数据库连接管理。
116 10
|
3月前
|
XML Java 数据格式
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
本文介绍了在使用Spring框架时,如何通过创建`applicationContext.xml`配置文件来管理对象。首先,在resources目录下新建XML配置文件,并通过IDEA自动生成部分配置。为完善配置,特别是添加AOP支持,可以通过IDEA的Live Templates功能自定义XML模板。具体步骤包括:连续按两次Shift搜索Live Templates,配置模板内容,输入特定前缀(如spring)并按Tab键即可快速生成完整的Spring配置文件。这样可以大大提高开发效率,减少重复工作。
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
|
3月前
|
Java Spring
【Spring配置相关】启动类为Current File,如何更改
问题场景:当我们切换类的界面的时候,重新启动的按钮是灰色的,不能使用,并且只有一个Current File 项目,下面介绍两种方法来解决这个问题。
|
3月前
|
Java Spring
【Spring配置】idea编码格式导致注解汉字无法保存
问题一:对于同一个项目,我们在使用idea的过程中,使用汉字注解完后,再打开该项目,汉字变成乱码问题二:本来a项目中,汉字注解调试好了,没有乱码了,但是创建出来的新的项目,写的注解又成乱码了。
|
3月前
|
Java Spring
【Spring配置】创建yml文件和properties或yml文件没有绿叶
本文主要针对,一个项目中怎么创建yml和properties两种不同文件,进行配置,和启动类没有绿叶标识进行解决。
|
3月前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
89 6
|
6月前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
379 18