原文:https://howtodoinjava.com/spring-mvc/spring-mvc-difference-between-contextannotation-config-vs-contextcomponent-scan/

在先前的文章中,我们在 Spring MVC 中学到的东西很少。 在这些教程中,我确实使用了<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另外引用了BeanBBeanC

  1. package com.howtodoinjava.beans;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.stereotype.Component;
  4. @SuppressWarnings("unused")
  5. @Component
  6. public class BeanA {
  7. private BeanB beanB;
  8. private BeanC beanC;
  9. public BeanA(){
  10. System.out.println("Creating bean BeanA");
  11. }
  12. @Autowired
  13. public void setBeanB(BeanB beanB) {
  14. System.out.println("Setting bean reference for BeanB");
  15. this.beanB = beanB;
  16. }
  17. @Autowired
  18. public void setBeanC(BeanC beanC) {
  19. System.out.println("Setting bean reference for BeanC");
  20. this.beanC = beanC;
  21. }
  22. }
  23. //Bean B
  24. package com.howtodoinjava.beans;
  25. import org.springframework.stereotype.Component;
  26. @Component
  27. public class BeanB {
  28. public BeanB(){
  29. System.out.println("Creating bean BeanB");
  30. }
  31. }
  32. //Bean C
  33. package com.howtodoinjava.beans;
  34. import org.springframework.stereotype.Component;
  35. @Component
  36. public class BeanC {
  37. public BeanC(){
  38. System.out.println("Creating bean BeanC");
  39. }
  40. }

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

  1. package com.howtodoinjava.test;
  2. import org.springframework.context.ApplicationContext;
  3. import org.springframework.context.support.ClassPathXmlApplicationContext;
  4. public class BeanDemo {
  5. public static void main(String[] args) {
  6. ApplicationContext context = new ClassPathXmlApplicationContext("classpath:beans.xml");
  7. }
  8. }

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

a)仅定义bean标签

  1. <bean id="beanA" class="com.howtodoinjava.beans.BeanA"></bean>
  2. <bean id="beanB" class="com.howtodoinjava.beans.BeanB"></bean>
  3. <bean id="beanC" class="com.howtodoinjava.beans.BeanC"></bean>
  4. Output:
  5. Creating bean BeanA
  6. Creating bean BeanB
  7. Creating bean BeanC

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

b)定义bean标签和ref属性

  1. <bean id="beanA" class="com.howtodoinjava.beans.BeanA">
  2. <property name="beanB" ref="beanB"></property>
  3. <property name="beanC" ref="beanC"></property>
  4. </bean>
  5. <bean id="beanB" class="com.howtodoinjava.beans.BeanB"></bean>
  6. <bean id="beanC" class="com.howtodoinjava.beans.BeanC"></bean>
  7. Output:
  8. Creating bean BeanA
  9. Creating bean BeanB
  10. Creating bean BeanC
  11. Setting bean reference for BeanB
  12. Setting bean reference for BeanC

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

c)仅使用<context:annotation-config/>

  1. <context:annotation-config />
  2. //No Output

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

d)将<context:annotation-config>bean声明一起使用

  1. <context:annotation-config />
  2. <bean id="beanA" class="com.howtodoinjava.beans.BeanA"></bean>
  3. <bean id="beanB" class="com.howtodoinjava.beans.BeanB"></bean>
  4. <bean id="beanC" class="com.howtodoinjava.beans.BeanC"></bean>
  5. Output:
  6. Creating bean BeanA
  7. Creating bean BeanB
  8. Setting bean reference for BeanB
  9. Creating bean BeanC
  10. Setting bean reference for BeanC

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

e)仅使用<context:component-scan/>

  1. <context:component-scan base-package="com.howtodoinjava.beans" />
  2. Output:
  3. Creating bean BeanA
  4. Creating bean BeanB
  5. Setting bean reference for BeanB
  6. Creating bean BeanC
  7. Setting bean reference for BeanC

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

f)同时使用<context:component-scan><context:annotation-config>

  1. <context:annotation-config />
  2. <context:component-scan base-package="com.howtodoinjava.beans" />
  3. <bean id="beanA" class="com.howtodoinjava.beans.BeanA"></bean>
  4. <bean id="beanB" class="com.howtodoinjava.beans.BeanB"></bean>
  5. <bean id="beanC" class="com.howtodoinjava.beans.BeanC"></bean>
  6. Output:
  7. Creating bean BeanA
  8. Creating bean BeanB
  9. Setting bean reference for BeanB
  10. Creating bean BeanC
  11. Setting bean reference for BeanC

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

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

下载源码

祝您学习愉快!