Spring 基于 XML 的装配通常采用两种实现方式,即我们在《Spring依赖注入》一节介绍的 setter 注入和构造注入。本节介绍如何配置自动装配。
自动装配就是指 Spring 容器在不使用 <constructor-arg> 和<property> 标签的情况下,可以自动装配(autowire)相互协作的 Bean 之间的关联关系,将一个 Bean 注入其他 Bean 的 Property 中。
使用自动装配需要配置 <bean> 元素的 autowire 属性。autowire 属性有五个值,具体说明如下表所示。
名称 | 说明 |
---|---|
no | 默认值,表示不使用自动装配,Bean 依赖必须通过 ref 元素定义。 |
byName | 根据 Property 的 name 自动装配,如果一个 Bean 的 name 和另一个 Bean 中的 Property 的 name 相同,则自动装配这个 Bean 到 Property 中。 |
byType | 根据 Property 的数据类型(Type)自动装配,如果一个 Bean 的数据类型兼容另一个 Bean 中 Property 的数据类型,则自动装配。 |
constructor | 类似于 byType,根据构造方法参数的数据类型,进行 byType 模式的自动装配。 |
autodetect(3.0版本不支持) | 如果 Bean 中有默认的构造方法,则用 constructor 模式,否则用 byType 模式。 |
示例
下面使用 Eclipse IDE 演示 Spring Bean 的自动装配,步骤如下:
- 创建 SpringDemo 项目,并在 src 目录下创建 net.biancheng 包。
- 添加相应的 jar 包,可以参考《第一个Spring程序》一节。
- 在 net.biancheng 包下创建 Person、Man 和 MainApp 类。
- 在 src 目录下创建 Spring 配置文件 Beans.xml。
- 运行 SpringDemo 项目。
Person 类代码如下。
package net.biancheng; public class Person { private Man man; public Person(Man man) { System.out.println("在Person的构造函数内"); this.man = man; } public void man() { man.show(); } }
Man 类代码如下。
package net.biancheng; public class Man { private String name; private int age; public Man() { System.out.println("在man的构造函数内"); } public Man(String name, int age) { System.out.println("在man的有参构造函数内"); this.name = name; this.age = age; } public void show() { System.out.println("名称:" + name + "/n年龄:" + age); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
MainApp 类代码如下。
package net.biancheng; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); Person person = (Person) context.getBean("person"); person.man(); } }
1)不使用自动装配(autowire="no")
autowire="no" 表示不使用自动装配,需要手动注入,Bean 依赖通过 ref 元素定义,Beans.xml 配置文件如下。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="man" class="net.biancheng.Man"> <constructor-arg value="bianchengbang" /> <constructor-arg value="12" type="int" /> </bean> <bean id="person" class="net.biancheng.Person" autowire="no"> <constructor-arg ref="man" type="java.lang.String"/> </bean> </beans>
2)按名称自动装配(autowire="byName")
autowire="byName" 表示按属性名称自动装配,XML 文件中 Bean 的 id 必须与类中的属性名称相同。配置文件内容修改如下。
<bean id="man" class="net.biancheng.Man"> <constructor-arg value="bianchengbang" /> <constructor-arg value="12" type="int" /> </bean> <bean id="person" class="net.biancheng.Person" autowire="byName"/>
运行结果如下。
在man的有参构造函数内
在Person的构造函数内
名称:bianchengbang
年龄:12
如果更改 Bean 的名称,很可能不会注入依赖项。
将 Bean 的名称更改为 man1,配置文件如下:
<bean id="man1" class="net.biancheng.Man"> <constructor-arg value="bianchengbang" /> <constructor-arg value="12" type="int" /> </bean> <bean id="person" class="net.biancheng.Person" autowire="byName"/>
注入失败,异常信息为:
在man的有参构造函数内
Exception in thread "main" java.lang.NullPointerException
at net.biancheng.Person.man(Person.java:16)
at net.biancheng.MainApp.main(MainApp.java:10)
3)按类型自动装配(autowire="byType")
XML 文件中 Bean 的 id 与类中的属性名称可以不同,但必须只有一个类型的 Bean。配置文件内容修改如下。
<bean id="man1" class="net.biancheng.Man"> <constructor-arg value="bianchengbang" /> <constructor-arg value="12" type="int" /> </bean> <bean id="person" class="net.biancheng.Person" autowire="byType"/>
运行结果如下。
在man的有参构造函数内
在Person的构造函数内
名称:bianchengbang
年龄:12
如果您有相同类型的多个 Bean,则注入失败,并且引发异常。
添加 id 为 man2 的 Bean,配置文件代码如下。
<bean id="man1" class="net.biancheng.Man"> <constructor-arg value="bianchengbang" /> <constructor-arg value="12" type="int" /> </bean> <bean id="man2" class="net.biancheng.Man"> <constructor-arg value="bianchengbang" /> <constructor-arg value="12" type="int" /> </bean> <bean id="person" class="net.biancheng.Person" autowire="byType"/>
异常信息为:
在man的有参构造函数内
在man的有参构造函数内
一月 26, 2021 1:34:14 下午 org.springframework.context.support.AbstractApplicationContext refresh
警告: Exception encountered during context initialization – cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'person' defined in class path resource [Beans.xml]: Unsatisfied dependency expressed through bean property 'man'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'net.biancheng.Man' available: expected single matching bean but found 2: man1,man2
…
4)构造函数自动装配(autowire="constructor")
修改 Person 类的代码。
package net.biancheng; public class Person { private Man man; public Person(Man man) { System.out.println("在Person的构造方法内"); this.man = man; } public Man getMan() { return man; } public void man() { man.show(); } }
类中构造函数的参数必须在配置文件中有相同的类型,配置文件内容修改如下。
<bean id="man" class="net.biancheng.Man"> <constructor-arg value="bianchengbang" /> <constructor-arg value="12" type="int" /> </bean> <bean id="person" class="net.biancheng.Person" autowire="constructor"/>
运行结果如下。
在man的有参构造函数内
在Person的构造函数内
名称:bianchengbang
年龄:12
自动装配的优缺点
优点
- 自动装配只需要较少的代码就可以实现依赖注入。
缺点
- 不能自动装配简单数据类型,比如 int、boolean、String 等。
- 相比较显示装配,自动装配不受程序员控制。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/4599.html