https://howtodoinjava.com/spring-core/spring-beans-autowiring-concepts/
在 Spring 框架中,遵循配置文件中的 bean 依赖关系是一种很好的做法,因此 Spring 容器能够自动关联 Bean 之间的关系。 这意味着可以通过检查BeanFactory
的内容来自动让 Spring 为您的 bean 解决协作者(其他 bean)。 这称为 SpringBean 自动装配。
自动装配功能具有四种模式。 这些是no
,byName
,byType
和constructor
。
另一种自动装配模式autodetect
已废弃。文档说,autodetect
选项提供了太多的“魔力”,因此首选更明确的声明。
- XML 配置中的默认自动装配模式为
no
。 - Java 配置中的默认自动装配模式为
byType
。
Spring bean 自动装配模式
1. 自动装配模式
如上图所示,有五种自动装配模式。 让我们一一讨论。
该选项是 spring 框架的默认选项,这意味着自动装配为OFF
。 您必须使用 bean 定义中的<property>
标签显式设置依赖项。
此选项启用基于 bean 名称的依赖项注入。 在 Bean 中自动装配属性时,属性名称用于在配置文件中搜索匹配的 Bean 定义。 如果找到这样的 bean,则将其注入属性。 如果找不到这样的 bean,则会引发错误。
阅读更多: 按名字自动装配示例
此选项启用基于 bean 类型的依赖项注入。 在 bean 中自动装配属性时,属性的类类型用于在配置文件中搜索匹配的 bean 定义。 如果找到这样的 bean,则将其注入属性。 如果找不到这样的 bean,则会引发错误。
阅读更多:按类型自动装配示例
constructor
的自动装配与byType
相似,但适用于构造函数参数。 在启用自动装配的 bean 中,它将查找构造函数参数的类类型,然后对所有构造函数参数执行自动装配bytype
。 请注意,如果容器中没有一个完全属于构造函数参数类型的 bean,则会引发致命错误。
阅读更多:通过构造器示例自动装配
2. @Autowired
注解
除了 bean 配置文件中提供的自动装配模式外,还可以使用@Autowired
注解在 bean 类中指定自动装配。 要在 bean 类中使用@Autowired
注解,必须首先使用以下配置在 spring 应用程序中启用注解。
2.1. 启用注解配置
applicationContext.xml
<context:annotation-config />
使用配置文件中的AutowiredAnnotationBeanPostProcessor
bean 定义可以实现相同的目的。
<bean class ="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
2.2. 使用@Autowired
注解
现在,启用注解配置后,您可以使用@Autowired
随意地自动绑定 bean 依赖项。 这可以通过三种方式完成:
2.2.1. @Autowired
属性
在属性上使用@Autowired
时,等效于在配置文件中通过byType
进行自动装配。
EmployeeBean.java
public class EmployeeBean
{
@Autowired
private DepartmentBean departmentBean;
public DepartmentBean getDepartmentBean() {
return departmentBean;
}
public void setDepartmentBean(DepartmentBean departmentBean) {
this.departmentBean = departmentBean;
}
//More code
}
2.2.2. 属性设置器上的@Autowired
当在设置器上使用@Autowired
时,它也等效于在配置文件中通过byType
进行自动装配。
EmployeeBean.java
public class EmployeeBean
{
private DepartmentBean departmentBean;
public DepartmentBean getDepartmentBean() {
return departmentBean;
}
@Autowired
public void setDepartmentBean(DepartmentBean departmentBean) {
this.departmentBean = departmentBean;
}
//More code
}
2.2.3. 构造函数上的@Autowired
在 bean 的构造函数上使用@Autowired
时,它也等效于在配置文件中通过constructor
自动装配。
EmployeeBean.java
package com.howtodoinjava.autowire.constructor;
public class EmployeeBean
{
@Autowired
public EmployeeBean(DepartmentBean departmentBean)
{
this.departmentBean = departmentBean;
}
private DepartmentBean departmentBean;
public DepartmentBean getDepartmentBean() {
return departmentBean;
}
public void setDepartmentBean(DepartmentBean departmentBean) {
this.departmentBean = departmentBean;
}
//More code
}
3. @Qualifier
解决冲突
我们了解到,如果我们在byType
模式下使用自动装配,则会在依赖项中查找属性类类型。 如果找不到这样的类型,则会引发错误。 但是,如果有两个或更多相同类类型的 bean,该怎么办。
在这种情况下,spring 将无法选择正确的 bean 来注入属性,因此您将需要使用限定符来帮助容器。
要使用限定符解析特定的 bean,我们需要将@Qualifier
注解与@Autowired
注解一起使用,并将 bean 名称传递到注解参数中。 看看下面的例子:
EmployeeBean.java
public class EmployeeBean
{
@Autowired
@Qualifier("finance")
private DepartmentBean departmentBean;
public DepartmentBean getDepartmentBean() {
return departmentBean;
}
public void setDepartmentBean(DepartmentBean departmentBean) {
this.departmentBean = departmentBean;
}
//More code
}
其中重复的 Bean 如下:
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<context:annotation-config />
<bean id="employee" class="com.howtodoinjava.autowire.constructor.EmployeeBean" autowire="constructor">
<property name="fullName" value="Lokesh Gupta"/>
</bean>
<!--First bean of type DepartmentBean-->
<bean id="humanResource" class="com.howtodoinjava.autowire.constructor.DepartmentBean" >
<property name="name" value="Human Resource" />
</bean>
<!--Second bean of type DepartmentBean-->
<bean id="finance" class="com.howtodoinjava.autowire.constructor.DepartmentBean" >
<property name="name" value="Finance" />
</bean>
</beans>
4. 使用required=false
进行错误安全的自动装配
即使您在自动装配 Bean 依赖项时已格外小心,仍然可能会发现奇怪的查找失败。 因此,要解决此问题,您将需要使自动装配成为可选的,以便在未找到依赖项的情况下,应用程序不应引发任何异常,而自动装配应被忽略。
这可以通过两种方式完成:
- 如果要使特定 bean 对于特定 bean 属性非强制装配,请在
@Autowired
注解中使用required="false"
属性。EmployeeBean.java
@Autowired (required=false)
@Qualifier ("finance")
private DepartmentBean departmentBean;
- 如果要在全局级别上应用可选自动装配,即对所有 bean 中的所有属性进行应用; 使用以下配置。
beans.xml
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">
<property name="requiredParameterValue" value="false" />
</bean>
5. 从自动装配中排除 bean
默认情况下,自动装配扫描并匹配作用域中的所有 bean 定义。 如果要排除某些 bean 定义,以使它们无法通过自动装配方式注入,则可以使用设置为false
的autowire-candidate
来实现。
如果将
autowire-candidate
用作false
,则将 bean 排除在自动装配候选之外。 它将特定的 bean 定义完全排除在自动装配基础结构之外。beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<context:annotation-config />
<bean id="employee" class="com.howtodoinjava.autowire.constructor.EmployeeBean" autowire="constructor">
<property name="fullName" value="Lokesh Gupta"/>
</bean>
<!--Will be available for autowiring-->
<bean id="humanResource" class="com.howtodoinjava.autowire.constructor.DepartmentBean" >
<property name="name" value="Human Resource" />
</bean>
<!--Will not participate in autowiring-->
<bean id="finance" class="com.howtodoinjava.autowire.constructor.DepartmentBean" autowire-candidate="false">
<property name="name" value="Finance" />
</bean>
</beans>
另一个选择是在 bean 名称上基于模式匹配限制自动装配候选。 顶层的
<beans />
元素在其default-autowire-candidates
属性中接受一个或多个模式。
例如,要将自动装配候选状态限制为名称以Impl
结尾的任何 bean,请提供值*Impl
。 要提供多种模式,请在以逗号分隔的列表中定义它们。beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans default-autowire-candidates="*Impl,*Dao">
<context:annotation-config />
<bean id="employee" class="com.howtodoinjava.autowire.constructor.EmployeeBean" autowire="constructor">
<property name="fullName" value="Lokesh Gupta"/>
</bean>
<!--Will be available for autowiring-->
<bean id="humanResource" class="com.howtodoinjava.autowire.constructor.DepartmentBean" >
<property name="name" value="Human Resource" />
</bean>
<!--Will not participate in autowiring-->
<bean id="finance" class="com.howtodoinjava.autowire.constructor.DepartmentBean" autowire-candidate="false">
<property name="name" value="Finance" />
</bean>
</beans>
请注意,bean 定义的autowire-candidate
属性的显式值true
或false
始终优先,而对于此类 bean,模式匹配规则将不适用。
这就是 Spring bean 自动装配的全部内容。 如有疑问,请发表评论。
学习愉快!