企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 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) **祝您学习愉快!**