目录
(1)不使用自动装配的 Beans.xml 配置:autowire="no"
Bean 的装配可以理解为依赖关系注入,Bean 的装配方式也就是 Bean 的依赖注入方式。Spring 容器支持多种装配 Bean 的方式,如基于 XML 的 Bean 装配、基于注解的 Bean 装配和自动装配等。// 常见的注入方式有,通过bean名称注入和通过bean类型注入
1、基于 XML 配置的 Bean 装配
自动装配就是指 Spring 容器在不使用 <constructor-arg> 和<property> 标签的情况下,可以自动装配(autowire)相互协作的 Bean 之间的依赖关系,即将一个 Bean 实例注入到其他 Bean 的属性中。
下面使用 IntelliJ IDEA 演示通过构造函数注入依赖项,步骤如下:
- 创建 Spring 项目,并在 src 目录下创建 com.spring_learn 包。
- 在 com.spring_learn 包下创建 Person、Man 和 MainApp 类。
- 在 src 目录下创建 Spring 配置文件 Beans.xml。
- 运行 Spring 项目。
以上步骤的 Java 代码请参照 Spring 依赖注入中的 Java 代码
(1)不使用自动装配的 Beans.xml 配置: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="com.swadian.spring_learn.Man">
<constructor-arg value="swadian2008" />
<constructor-arg value="20" type="int" />
</bean>
<bean id="person" class="com.swadian.spring_learn.Person" autowire="no">
<constructor-arg ref="man" type="com.swadian.spring_learn.Man"/>
</bean>
</beans>
(2)按名称自动装配:autowire="byName"
autowire="byName" 表示按属性名称自动装配,XML 文件中 Bean 的 id 必须与类中的属性名称相同。配置文件内容如下:
<?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="com.swadian.spring_learn.Man">
<constructor-arg value="swadian2008" />
<constructor-arg value="20" type="int" />
</bean>
<!--按名称装配-->
<bean id="person" class="com.swadian.spring_learn.Person" autowire="byName"/>
</beans>
如果更改 Bean 的名称,很可能不会注入依赖项。如果将 Bean 的名称更改为 man_1,内容如下:
<!--改为名称不一致-->
<bean id="man_1" class="com.swadian.spring_learn.Man">
<constructor-arg value="swadian2008" />
<constructor-arg value="20" type="int" />
</bean>
<!--按名称装配-->
<bean id="person" class="com.swadian.spring_learn.Person" autowire="byName"/>
那么启动程序时,依赖项将注入失败:
(3)按类型自动装配:autowire="byType"
XML 文件中 Bean 的 id 与类中的属性名称可以不同,但必须只有一个类型的 Bean。配置文件内容修改如下。
<?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_1" class="com.swadian.spring_learn.Man">
<constructor-arg value="swadian2008" />
<constructor-arg value="20" type="int" />
</bean>
<!--按类型装配-->
<bean id="person" class="com.swadian.spring_learn.Person" autowire="byType"/>
</beans>
如果容器中具备多个相同类型的 Bean,依赖项将注入失败,并且引发程序异常。添加 id 为 man_2 的 Bean,修改内容如下:
<!--名称不一致-->
<bean id="man_1" class="com.swadian.spring_learn.Man">
<constructor-arg value="swadian2008" />
<constructor-arg value="20" type="int" />
</bean>
<!--增加同类型bean-->
<bean id="man_2" class="com.swadian.spring_learn.Man">
<constructor-arg value="swadian2010" />
<constructor-arg value="22" type="int" />
</bean>
<!--按类型装配-->
<bean id="person" class="com.swadian.spring_learn.Person" autowire="byType"/>
程序运行时,将抛出如下异常信息:
Exception in thread "main" 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 'com.swadian.spring_learn.Man' available: expected single matching bean but found 2: man_1,man_2
2、基于 Annotation 的 Bean 装配
在 Spring 中,尽管可以使用 XML 配置文件实现 Bean 的装配工作,但如果应用中 Bean 的数量较多,会导致 XML 配置文件过于臃肿,从而给维护和升级带来一定的困难。
Java 从 JDK 5.0 以后,提供了 Annotation(注解)功能,Spring 2.5 版本开始也提供了对 Annotation 技术的全面支持,我们可以使用注解来配置依赖注入。
(1)@Autowired 默认按类型装配
可以应用到 Bean 的属性变量、属性的 setter 方法、非 setter 方法及构造函数等,配合对应的注解处理器完成 Bean 的自动配置工作。默认按照 Bean 的类型进行装配。
(2)@Qualifier 按名称装配
与 @Autowired 注解配合使用,会将默认的按 Bean 类型装配修改为按 Bean 的实例名称装配,Bean 的实例名称由 @Qualifier 注解的参数指定。
(3)@Resource 默认按名称装配
作用与 Autowired 相同,区别在于 @Autowired 默认按照 Bean 类型装配,而 @Resource 默认按照 Bean 实例名称进行装配。
@Resource 中有两个重要属性:name 和 type。
Spring 将 name 属性解析为 Bean 的实例名称,type 属性解析为 Bean 的实例类型。如果指定 name 属性,则按实例名称进行装配;如果指定 type 属性,则按 Bean 类型进行装配。如果都不指定,则先按 Bean 实例名称装配,如果不能匹配,则再按照 Bean 类型进行装配;如果都无法匹配,则抛出 NoSuchBeanDefinitionException 异常。
3、自动装配的优缺点
优点:自动装配只需要较少的代码就可以实现依赖注入。
缺点:不能自动装配简单数据类型,比如 int、boolean、String 等,相比较显式的装配,自动装配不受程序员控制。