Spring MVC中是否需要使用context:annotation-config标签?

16 浏览
0 Comments

Spring MVC中是否需要使用context:annotation-config标签?

我正在学习Spring 3,但似乎没有掌握 的功能。

据我所读,它们似乎处理不同的注解(@Required@Autowired 等与 @Component@Repository@Service等),但也根据我所读,它们注册相同的bean后处理类。

为了让我更加困惑, 还有一个 annotation-config 属性。

有人能解释一下这些标签吗?它们有什么相似之处,有什么不同之处,其中一个是否已被取代,它们是否相互补充,我需要其中之一还是两者都需要?

admin 更改状态以发布 2023年5月20日
0
0 Comments

我发现了这个不错的总结,其中列出了哪些声明会识别哪些注释。通过学习它,您会发现识别的注释是识别的注释的超集,包括:

  • @Component@Service@Repository@Controller@Endpoint
  • @Configuration@Bean@Lazy@Scope@Order@Primary@Profile@DependsOn@Import@ImportResource

正如您所看到的,使用类路径组件扫描和Java @Configuration功能在逻辑上延伸

0
0 Comments

用于激活应用上下文中已注册的bean的注解(无论它们是使用XML定义还是通过包扫描定义)。

也可以执行的功能,但 还会扫描包以查找并注册应用上下文中的bean。

我将使用一些例子来展示差异/相似性。

让我们从三个类型为ABC的基本设置开始,其中BC被注入到A中。

package com.xxx;
public class B {
  public B() {
    System.out.println("creating bean B: " + this);
  }
}
package com.xxx;
public class C {
  public C() {
    System.out.println("creating bean C: " + this);
  }
}
package com.yyy;
import com.xxx.B;
import com.xxx.C;
public class A { 
  private B bbb;
  private C ccc;
  public A() {
    System.out.println("creating bean A: " + this);
  }
  public void setBbb(B bbb) {
    System.out.println("setting A.bbb with " + bbb);
    this.bbb = bbb;
  }
  public void setCcc(C ccc) {
    System.out.println("setting A.ccc with " + ccc);
    this.ccc = ccc; 
  }
}

使用以下XML配置:




  
  

加载上下文会产生以下输出:

creating bean B: com.xxx.B@c2ff5
creating bean C: com.xxx.C@1e8a1f6
creating bean A: com.yyy.A@1e152c5
setting A.bbb with com.xxx.B@c2ff5
setting A.ccc with com.xxx.C@1e8a1f6

好的,这是预期输出。但这是“旧风格”的Spring。现在我们有注解,所以让我们使用它们来简化XML。

首先,让我们像这样自动连接到A上的bbbccc属性:

package com.yyy;
import org.springframework.beans.factory.annotation.Autowired;
import com.xxx.B;
import com.xxx.C;
public class A { 
  private B bbb;
  private C ccc;
  public A() {
    System.out.println("creating bean A: " + this);
  }
  @Autowired
  public void setBbb(B bbb) {
    System.out.println("setting A.bbb with " + bbb);
    this.bbb = bbb;
  }
  @Autowired
  public void setCcc(C ccc) {
    System.out.println("setting A.ccc with " + ccc);
    this.ccc = ccc;
  }
}

这允许我从XML中删除以下行:



我的XML现在简化为:




当我加载上下文时,我会得到以下输出:

creating bean B: com.xxx.B@5e5a50
creating bean C: com.xxx.C@54a328
creating bean A: com.yyy.A@a3d4cf

好的,这是错误的!发生了什么?为什么我的属性没有被自动连接?

好吧,注释是很好的功能,但是单独使用它们什么也做不了。它们只是注释的东西。你需要一个处理工具来查找注释并对它们进行一些操作。

拯救的方法是。这激活其自身所在的应用上下文中定义的bean上的注释操作。

如果我将XML更改为:





加载应用上下文时,我会得到正确的结果:

creating bean B: com.xxx.B@15663a2
creating bean C: com.xxx.C@cd5f8b
creating bean A: com.yyy.A@157aa53
setting A.bbb with com.xxx.B@15663a2
setting A.ccc with com.xxx.C@cd5f8b

好的,这不错,但是我从XML中删除了两行并添加了一行。 这并不是很大的差异。 注释的想法是应该删除XML。

所以让我们删除XML定义并用注释替换它们所有:

package com.xxx;
import org.springframework.stereotype.Component;
@Component
public class B {
  public B() {
    System.out.println("creating bean B: " + this);
  }
}
package com.xxx;
import org.springframework.stereotype.Component;
@Component
public class C {
  public C() {
    System.out.println("creating bean C: " + this);
  }
}
package com.yyy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.xxx.B;
import com.xxx.C;
@Component
public class A { 
  private B bbb;
  private C ccc;
  public A() {
    System.out.println("creating bean A: " + this);
  }
  @Autowired
  public void setBbb(B bbb) {
    System.out.println("setting A.bbb with " + bbb);
    this.bbb = bbb;
  }
  @Autowired
  public void setCcc(C ccc) {
    System.out.println("setting A.ccc with " + ccc);
    this.ccc = ccc;
  }
}

而在XML中,我们只保留以下内容:


我们加载上下文,结果是......什么也没有。没有创建任何bean,没有自动连接任何bean。没有!

那是因为,正如我在第一段中所说的,仅适用于在应用上下文中注册的bean。因为我删除了三个bean的XML配置,所以没有创建bean,没有“目标”可供处理。

但对于来说,这不会是问题,它可以扫描一个包以寻找要处理的“目标”。让我们将XML配置的内容更改为以下条目:


当我加载上下文时,我得到以下输出:

creating bean B: com.xxx.B@1be0f0a
creating bean C: com.xxx.C@80d1ff

嗯...有些东西缺失了。为什么?

如果你仔细看类,类 A 的包为 com.yyy,但我在 中指定了使用包 com.xxx,所以完全错过了我的 A 类,只选中了 BC,它们位于 com.xxx 包中。

要修复这个问题,我还需添加另一个包:


现在,我们得到了预期的结果:

creating bean B: com.xxx.B@cd5f8b
creating bean C: com.xxx.C@15ac3c9
creating bean A: com.yyy.A@ec4a87
setting A.bbb with com.xxx.B@cd5f8b
setting A.ccc with com.xxx.C@15ac3c9

就这样!现在你不再需要 XML 定义,而是使用注解。

最终的例子,保留已注释的类 ABC,并添加以下 XML,加载上下文后我们会得到什么?



我们仍然得到正确的结果:

creating bean B: com.xxx.B@157aa53
creating bean C: com.xxx.C@ec4a87
creating bean A: com.yyy.A@1d64c37
setting A.bbb with com.xxx.B@157aa53
setting A.ccc with com.xxx.C@ec4a87

即使类 A 的 bean 没有被扫描获取,处理工具仍然会应用于所有在应用上下文中注册的 bean,包括手动注册在 XML 中的 A

但如果我们有以下 XML,当我们同时指定 ,我们会得到重复的 bean 吗?




不会有重复,我们会得到预期的结果:

creating bean B: com.xxx.B@157aa53
creating bean C: com.xxx.C@ec4a87
creating bean A: com.yyy.A@1d64c37
setting A.bbb with com.xxx.B@157aa53
setting A.ccc with com.xxx.C@ec4a87

这是因为两个标签都注册了相同的处理工具(如果指定了 ,则可以省略 ),但 Spring 确保仅运行一次。

即使您多次注册处理工具,Spring 仍会确保它们只执行一次;这个 XML:








仍会生成以下结果:

creating bean B: com.xxx.B@157aa53
creating bean C: com.xxx.C@ec4a87
creating bean A: com.yyy.A@25d2b2
setting A.bbb with com.xxx.B@157aa53
setting A.ccc with com.xxx.C@ec4a87

好,关于这个就不多说了。

希望与 @Tomasz Nurkiewicz 和 @Sean Patrick Floyd 的回应一起,这些信息足以让你了解 的工作原理。

0