Spring框架(5) —— 自动装配

Spring Beans 自动装配

  • 我们已经学会如何使用<bean>元素来声明 bean 和通过使用 XML 配置文件中的<constructor-arg><property>元素来注入 。而Spring 容器还可以在不使用<constructor-arg><property> 元素的情况下自动装配相互协作的 bean 之间的关系,这有助于减少编写一个大的基于 Spring 的应用程序的 XML 配置的数量。

自动装配模式

  • 下列自动装配模式,它们可用于指示 Spring 容器为来使用自动装配进行依赖注入。你可以使用<bean>元素的 autowire 属性为一个 bean 定义指定自动装配模式。
    • no
      • 默认设置,它意味着没有自动装配,表示我们需要使用显式的bean引用来注入依赖。
    • byName
      • 属性名自动装配。
      • Spring 先匹配POJO类的类成员名称与配置文件中<bean>标签的id属性,如果名称相同,则匹配类型;类型相同,则配对成功。
    • byType
      • 属性数据类型自动装配。
      • Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byType。然后如果它的类型匹配配置文件中的一个确切的 bean 名称,它将尝试匹配和连接属性的类型。如果存在不止一个这样的 bean,则一个致命的异常将会被抛出。
    • constructor
      • 类似于 byType,但该类型适用于构造函数参数类型。如果在容器中没有一个构造函数参数类型的 bean,则一个致命错误将会发生。
    • autodetect
      • Spring首先尝试通过 constructor 使用自动装配来连接,如果它不执行,Spring 尝试通过 byType 来自动装配。

自动装配的局限性

  • 当自动装配始终在同一个项目中使用时,它的效果最好。如果通常不使用自动装配,它可能会使开发人员混淆的使用它来连接只有一个或两个 bean 定义。不过,自动装配可以显著减少需要指定的属性或构造器参数,但你应该在使用它们之前考虑到自动装配的局限性和缺点。
    • 重写的可能性
      • 你可以使用总是重写自动装配的 <constructor-arg>和 <property> 设置来指定依赖关系。
    • 原始数据类型
      • 你不能自动装配所谓的简单类型包括基本类型,字符串和类。
    • 混乱的本质
      • 自动装配不如显式装配精确,所以如果可能的话尽可能使用显式装配。

Spring 自动装配 ‘byName’

  • 这种模式由属性名称指定自动装配。Spring 容器看作 beans,在 XML 配置文件中 beans 的 auto-wire 属性设置为 byName。然后,它尝试将它的属性与配置文件中定义为相同名称的 beans 进行匹配和连接。如果找到匹配项,它将注入这些 beans,否则,它将抛出异常。
  • 例如,在配置文件中,如果一个 bean 定义设置为自动装配 byName,并且它包含 spellChecker 属性(即,它有一个 setSpellChecker(…) 方法),那么 Spring 就会查找定义名为 spellChecker 的 bean,并且用它来设置这个属性。你仍然可以使用 <property> 标签连接其余的属性。下面的例子将说明这个概念。

(1)TextEditor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package cn.water.spring_autowire.byName;

public class TextEditor {

/* 成员变量 */
private SpellChecker spellChecker;

/* Setter方法 */
public void setSpellChecker( SpellChecker spellChecker ){
this.spellChecker = spellChecker;
}

/* Getter方法 */
public SpellChecker getSpellChecker() {
return spellChecker;
}

/* 成员方法 */
public void spellCheck() {
spellChecker.checkSpelling();
}
}

(2)SpellChecker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package cn.water.spring_autowire.byName;

public class SpellChecker {

/* 构造函数 */
public SpellChecker(){
System.out.println("SpellChecker constructor" );
}

/* 成员方法 */
public void checkSpelling() {
System.out.println("checkSpelling..." );
}
}

(3)Beans.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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">

<!-- TextEditor -->
<bean id="textEditor"
class="cn.water.spring_autowire.byName.TextEditor"
autowire="byName">
</bean>

<!-- SpellChecker
id属性:类成员名称 -->
<bean id="spellChecker"
class="cn.water.spring_autowire.byName.SpellChecker">
</bean>
</beans>

(4)测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package cn.water.spring_autowire.byName;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
public static void main(String[] args) {
/* 1.获取容器 */
ApplicationContext context =
new ClassPathXmlApplicationContext("spring_autowire/byName/Beans.xml");
/* 2.获取对象 */
TextEditor editor = (TextEditor) context.getBean("textEditor");
/* 3.调用方法 */
editor.spellCheck();
}
}

(5)结果

1
2
SpellChecker constructor
checkSpelling...

Spring 自动装配 ‘byType’

  • 这种模式由属性类型指定自动装配。Spring 容器看作 beans,在 XML 配置文件中 beans 的 autowire 属性设置为 byType。然后,如果它的 type 恰好与配置文件中 beans 名称中的一个相匹配,它将尝试匹配和连接它的属性。如果找到匹配项,它将注入这些 beans,否则,它将抛出异常。
  • 例如,在配置文件中,如果一个 bean 定义设置为自动装配 byType*,并且它包含 *SpellChecker 类型的 spellChecker 属性,那么 Spring 就会查找定义名为 SpellChecker 的 bean,并且用它来设置这个属性。你仍然可以使用<property> 标签连接其余属性。下面的例子将说明这个概念,你会发现和上面的例子没有什么区别,除了 XML 配置文件已经被改变。

(1)TextEditor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package cn.water.spring_autowire.byType;

public class TextEditor {

/* 成员变量 */
private SpellChecker spellChecker;

/* Setter方法 */
public void setSpellChecker( SpellChecker spellChecker ){
this.spellChecker = spellChecker;
}

/* 成员方法 */
public void spellCheck() {
spellChecker.checkSpelling();
}
}

(2)SpellChecker
(3)Beans.xml

1
2
3
4
5
6
7
8
9
10
11
<!-- TextEditor -->
<bean id="textEditor"
class="cn.water.spring_autowire.byType.TextEditor"
autowire="byType">
</bean>

<!-- SpellChecker
id属性:类型名称 -->
<bean id="SpellChecker"
class="cn.water.spring_autowire.byType.SpellChecker">
</bean>

(4)测试类
(5)结果

1
2
SpellChecker constructor
checkSpelling...

Spring 由构造函数自动装配

  • 这种模式与 byType 非常相似,但它应用于构造器参数。Spring 容器看作 beans,在 XML 配置文件中 beans 的 autowire属性设置为 constructor。然后,它尝试把它的构造函数的参数与配置文件中 beans 名称中的一个进行匹配和连线。如果找到匹配项,它会注入这些 bean,否则,它会抛出异常。
  • 例如,在配置文件中,如果一个 bean 定义设置为通过构造函数*自动装配,而且它有一个带有 *SpellChecker 类型的参数之一的构造函数,那么 Spring 就会查找定义名为 SpellChecker 的 bean,并用它来设置构造函数的参数。你仍然可以使用 <constructor-arg> 标签连接其余属性。下面的例子将说明这个概念。

(1)TextEditor

将Setter方法变为构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package cn.water.spring_autowire.byName;

public class TextEditor {

/* 成员变量 */
private SpellChecker spellChecker;

/* 构造方法 */
public TextEditor( SpellChecker spellChecker ) {
this.spellChecker = spellChecker;
}

/* 成员方法 */
public void spellCheck() {
spellChecker.checkSpelling();
}
}

(2)SpellChecker

(3)Beans.xml

除了autowire属性改成constructor之外,其他完全一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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">

<!-- TextEditor -->
<bean id="textEditor"
class="cn.water.spring_autowire.byName.TextEditor"
autowire="constructor">
</bean>

<!-- SpellChecker -->
<bean id="SpellChecker"
class="cn.water.spring_autowire.byName.SpellChecker">
</bean>
</beans>

(4)测试类

(5)结果

1
2
SpellChecker constructor
checkSpelling...
-------------本文结束-------------
Donate comment here