# Spring MVC：`<context:annotation-config>`与`<context:component-scan>`

> 原文：[https://howtodoinjava.com/spring-mvc/spring-mvc-difference-between-contextannotation-config-vs-contextcomponent-scan/](https://howtodoinjava.com/spring-mvc/spring-mvc-difference-between-contextannotation-config-vs-contextcomponent-scan/)

在先前的文章中，我们在 [**Spring MVC**](https://howtodoinjava.com) 中学到的东西很少。 在这些教程中，我确实使用了`<context:annotation-config>`或`<context:component-scan>`之类的标签，但是我没有对这些标签进行详细说明。 我正在写这篇文章，专门列出标签`<context:annotation-config>`和`<context:component-scan>`之间的区别，以便将来使用它们时，您将知道自己在做什么。

1）两个标签之间的第一个大区别是`<context:annotation-config>`是**用于在应用程序上下文**中激活已注册 bean 中的应用注解。 请注意，bean 是否通过哪种机制注册都没有关系，例如使用`<context:component-scan>`或在`application-context.xml`文件本身中定义。

2）第二差异是由第一差异本身驱动的。 它确实**在上下文中注册了 bean，并且还扫描了 bean 内部的注解并激活了它们**。 所以`<context:component-scan>`; 做`<context:annotation-config>`的工作，但另外它会扫描软件包并在应用程序上下文中注册 bean。

## `<context:component-scan>` vs `<context:annotation-config>`使用示例

我将通过一些示例详细说明这两个标签，这些示例对我们更有意义。 为了使示例简单，我仅创建 3 个 bean，然后尝试以各种方式在配置文件中对其进行配置，然后我们将看到控制台中各种配置之间的区别，其中将输出输出。

供参考，以下是 3 个 bean。 `BeanA`另外引用了`BeanB`和`BeanC`。

```java
package com.howtodoinjava.beans;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@SuppressWarnings("unused")
@Component
public class BeanA {

	private BeanB beanB;
	private BeanC beanC;

	public BeanA(){
		System.out.println("Creating bean BeanA");
	}

	@Autowired
	public void setBeanB(BeanB beanB) {
		System.out.println("Setting bean reference for BeanB");
		this.beanB = beanB;
	}

	@Autowired
	public void setBeanC(BeanC beanC) {
		System.out.println("Setting bean reference for BeanC");
		this.beanC = beanC;
	}
}

//Bean B

package com.howtodoinjava.beans;

import org.springframework.stereotype.Component;

@Component
public class BeanB {
	public BeanB(){
		System.out.println("Creating bean BeanB");
	}
}

//Bean C

package com.howtodoinjava.beans;

import org.springframework.stereotype.Component;

@Component
public class BeanC {
	public BeanC(){
		System.out.println("Creating bean BeanC");
	}
}

```

`BeanDemo`类用于加载和初始化应用程序上下文。

```java
package com.howtodoinjava.test;

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

public class BeanDemo {
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("classpath:beans.xml");
	}
}

```

现在，我们开始编写包含变体的配置文件`"beans.xml"`。 在下面的示例中，我将省略模式声明，以继续关注配置本身。

#### a）仅定义`bean`标签

```java
<bean id="beanA" class="com.howtodoinjava.beans.BeanA"></bean>
<bean id="beanB" class="com.howtodoinjava.beans.BeanB"></bean>
<bean id="beanC" class="com.howtodoinjava.beans.BeanC"></bean>

Output:

Creating bean BeanA
Creating bean BeanB
Creating bean BeanC

```

在这种情况下，因为我们没有使用任何属性/引用属性，所以创建了所有 3 个 bean，并且没有在`BeanA`中注入任何依赖项。

#### b）定义`bean`标签和`ref`属性

```java
<bean id="beanA" class="com.howtodoinjava.beans.BeanA">
	<property name="beanB" ref="beanB"></property>
	<property name="beanC" ref="beanC"></property>
</bean>
<bean id="beanB" class="com.howtodoinjava.beans.BeanB"></bean>
<bean id="beanC" class="com.howtodoinjava.beans.BeanC"></bean>

Output:

Creating bean BeanA
Creating bean BeanB
Creating bean BeanC
Setting bean reference for BeanB
Setting bean reference for BeanC

```

现在，还创建并注入了 bean。 难怪。

#### c）仅使用`<context:annotation-config/>`

```java
<context:annotation-config />

//No Output

```

正如我已经说过的，`<context:annotation-config />`仅在已经发现并注册的 bean 上激活注解。 在这里，我们没有发现任何 Bean，因此什么也没发生。

#### d）将`<context:annotation-config>`与`bean`声明一起使用

```java
<context:annotation-config />
<bean id="beanA" class="com.howtodoinjava.beans.BeanA"></bean>
<bean id="beanB" class="com.howtodoinjava.beans.BeanB"></bean>
<bean id="beanC" class="com.howtodoinjava.beans.BeanC"></bean>

Output:

Creating bean BeanA
Creating bean BeanB
Setting bean reference for BeanB
Creating bean BeanC
Setting bean reference for BeanC

```

在上面的配置中，我们使用`<bean>`标签发现了 bean。 现在，当我们使用`<context:annotation-config />`时，它只需激活`@Autowired`注解，就会在`BeanA`内部进行 bean 注入。

#### e）仅使用`<context:component-scan/>`

```java
<context:component-scan base-package="com.howtodoinjava.beans" />

Output:

Creating bean BeanA
Creating bean BeanB
Setting bean reference for BeanB
Creating bean BeanC
Setting bean reference for BeanC

```

上面的配置完成了我之前在文章开头提到的两件事。 它会进行 Bean 发现（在基本包中搜索`@Component`注解），然后激活其他注解（例如`Autowired`）。

#### f）同时使用`<context:component-scan>`和`<context:annotation-config>`

```java
<context:annotation-config />
<context:component-scan base-package="com.howtodoinjava.beans" />
<bean id="beanA" class="com.howtodoinjava.beans.BeanA"></bean>
<bean id="beanB" class="com.howtodoinjava.beans.BeanB"></bean>
<bean id="beanC" class="com.howtodoinjava.beans.BeanC"></bean>

Output:

Creating bean BeanA
Creating bean BeanB
Setting bean reference for BeanB
Creating bean BeanC
Setting bean reference for BeanC

```

奇怪！ 通过上述配置，我们两次发现了 bean，并且两次激活了注释。 但是输出只打印了一次。 为什么？ 因为 spring 具有足够的智能，如果使用相同或不同的方式多次注册任何配置处理，则仅注册一次。酷！

因此，在这里，我将结束本教程，并希望当您在下一个项目中使用这些标签时，它们将为您提供更清晰的画面。 随意下载源代码并使用它。

[下载源码](https://drive.google.com/file/d/0B7yo2HclmjI4dHFyeU9JVjFsa2s/edit?usp=sharing)

**祝您学习愉快！**