" 之间的区别"

11 浏览
0 Comments

" 之间的区别"

我正在学习Spring 3,但似乎无法掌握后面的功能。

从我所读的内容来看,它们似乎处理不同的注释(@Required@Autowired等 vs @Component@Repository@Service等),但据我所知,它们还会注册相同的bean后处理器类。

令我更加困惑的是,上有一个annotation-config属性。

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

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

我找到了这个很好的注解和声明的总结。通过学习它,您会发现识别比更多的注解,即:

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

正如您所看到的,在类路径组件扫描和Java @Configuration功能方面逻辑上扩展

0
0 Comments

用于激活在已经注册在应用程序上下文中的beans中的注释(无论是使用XML定义还是通过包扫描定义的)。

也可以做到的一样的事情,但还会扫描包,以在应用程序上下文中查找并注册beans。

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

让我们从包含A类型、BC的三个基本设置的beans开始,其中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。

首先,让我们像这样自动装配在bean 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

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

好吧,注释是一个不错的功能,但它本身什么也不做。它们只是注释。您需要一个处理工具来查找注释并对其做些什么。

来解救。它会激活在其自身定义的相同应用程序上下文中所定义的beans上找到的注释的操作。

如果我将我的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 类,而只捡起了位于com.xxx包的BC

为了解决这个问题,我还添加了另一个包:


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

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