区别<背景:注解配置> VS<背景:组件扫描>
我学习春天3,我似乎并没有把握&LT之后的功能;背景:注解配置>
和<背景:组件扫描>
I'm learning Spring 3 and I don't seem to grasp the functionality behind <context:annotation-config>
and <context:component-scan>
.
这是我读过他们似乎处理不同的批注(@Required,@Autowired等VS @Component,@Repository,@Service等),但也从我读过他们注册一个bean后处理器类。
From what I've read they seem to handle different annotations (@Required, @Autowired etc vs @Component, @Repository, @Service etc) but also from what I've read they register the same bean post processor classes.
要迷惑我更加,对℃的
。注释的配置
属性;背景:组件扫描&GT;
To confuse me even more, there is an annotation-config
attribute on <context:component-scan>
.
有人能摆脱这些标记的一些轻?什么是相似的,什么是不同的,是一家由其他替代,他们完成对方,我需要他们中的一个,两个?
Can someone shed some light on these tags? What's similar, what's different, is one superseded by the other, they complete each other, do I need one of them, both?
&LT;背景:注解配置&GT;
用于激活在应用程序已经注册的bean的注解上下文(如果他们使用XML或包扫描定义不管)。
<context:annotation-config>
is used to activate annotations in beans already registered in the application context (no matter if they were defined with XML or by package scanning).
&LT;背景:组件扫描&GT;
还可以做什么&LT;背景:注解配置&GT;
做但&LT;背景:组件扫描&GT;
也会扫描包发现和应用程序上下文注册豆类
<context:component-scan>
can also do what <context:annotation-config>
does but <context:component-scan>
also scans packages to find and register beans within the application context.
我将用一些例子来显示差异/相似之处。
I'll use some examples to show the differences/similarities.
让我们先从类型的三个豆基本设置 A
, B
和 ç
与 B
和 C
被注入到 A
。
Lets start with a basic setup of three beans of type A
, B
and C
, with B
and C
being injected into 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配置:
With the following XML configuration :
<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A">
<property name="bbb" ref="bBean" />
<property name="ccc" ref="cBean" />
</bean>
加载背景下产生下面的输出:
Loading the context produces the following output:
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
OK,这是预期的输出。但是,这是旧式春。现在我们有这样的注解让使用它们来简化XML。
OK, this is the expected output. But this is "old style" Spring. Now we have annotations so lets use those to simplify the XML.
首先,让自动装配的 BBB
和 CCC
的bean属性 A
像这样:
First, lets autowire the bbb
and ccc
properties on bean A
like so:
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删除以下行:
This allows me to remove the following rows from the XML:
<property name="bbb" ref="bBean" />
<property name="ccc" ref="cBean" />
我的XML现在简化为这样的:
My XML is now simplified to this:
<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />
当我打开我得到以下输出上下文:
When I load the context I get the following output:
creating bean B: com.xxx.B@5e5a50
creating bean C: com.xxx.C@54a328
creating bean A: com.yyy.A@a3d4cf
OK,这是错误的!发生了什么?为什么我的属性自动装配?
OK, this is wrong! What happened? Why aren't my properties autowired?
那么,注释是一个不错的功能,但自己又无能为力任何责任。他们只是标注的东西。你需要一个处理工具找到注解,并做一些与他们。
Well, annotations are a nice feature but by themselves they do nothing whatsoever. They just annotate stuff. You need a processing tool to find the annotations and do something with them.
&LT;背景:注解配置&GT;
救援。这将激活该发现对在本身的定义是相同的应用程序上下文中定义豆注解的行动。
<context:annotation-config>
to the rescue. This activates the actions for the annotations that it finds on the beans defined in the same application context where itself is defined.
如果我改变我的XML这样:
If I change my XML to this:
<context:annotation-config />
<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />
当我加载应用程序上下文获得正确的结果是:
when I load the application context I get the proper result:
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
OK,这是好的,但我已经删除从XML两行增加了一个。这不是一个非常大的差异。与注释的想法是,它应该删除XML
OK, this is nice, but I've removed two rows from the XML and added one. That's not a very big difference. The idea with annotations is that it's supposed to remove the XML.
因此,让我们删除XML定义和注释全部更换:
So let's remove the XML definitions and replace them all with annotations:
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我们只保留这样的:
While in the XML we only keep this:
<context:annotation-config />
我们加载的背景下,其结果就是什么都没有。创建无豆,无咖啡豆自动装配。没事!
We load the context and the result is... Nothing. No beans are created, no beans are autowired. Nothing!
这是因为,正如我在第一段说,在&LT;背景:注解配置/&GT;
仅适用于应用程序范围内注册的bean。因为我删除了XML配置为三豆没有创造豆和&LT;背景:注解配置/&GT;
没有指标上下工夫
That's because, as I said in the first paragraph, the <context:annotation-config />
only works on beans registered within the application context. Because I removed the XML configuration for the three beans there is no bean created and <context:annotation-config />
has no "targets" to work on.
但是,这不会是℃的问题;环境:组件扫描&GT;
它可以扫描包指标上下工夫。让我们改变XML配置的内容到以下项:
But that won't be a problem for <context:component-scan>
which can scan a package for "targets" to work on. Let's change the content of the XML config into the following entry:
<context:component-scan base-package="com.xxx" />
当我打开我得到以下输出上下文:
When I load the context I get the following output:
creating bean B: com.xxx.B@1be0f0a
creating bean C: com.xxx.C@80d1ff
嗯...缺少的东西。为什么?
Hmmmm... something is missing. Why?
如果您在班closelly看,类 A
有包 com.yyy
但我已经指定在&LT;背景:组件扫描&GT;
使用的软件包 com.xxx
所以这完全错过了我的 A
类,只有拿起 B
和 C
这是在 com.xxx
包。
If you look closelly at the classes, class A
has package com.yyy
but I've specified in the <context:component-scan>
to use package com.xxx
so this completely missed my A
class and only picked up B
and C
which are on the com.xxx
package.
要解决这个问题,我还添加此包其他:
To fix this, I add this other package also:
<context:component-scan base-package="com.xxx,com.yyy" />
,现在我们得到预期的结果:
and now we get the expected result:
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定义了,你有注释。
And that's it! Now you don't have XML definitions anymore, you have annotations.
最后一个例子,保持注释类 A
, B
和 C
并添加以下的XML,你会得到加载上下文后?
As a final example, keeping the annotated classes A
, B
and C
and adding the following to the XML, what will we get after loading the context?
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />
我们仍然可以得到正确的结果:
We still get the correct result:
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
即使这个bean类 A
不被扫描获得的加工工具仍然由&LT适用;背景:组件扫描&GT ;
上注册的所有bean
其中手动在XML注册的应用程序的背景下,即使是 A
。
Even if the bean for class A
isn't obtained by scanning, the processing tools are still applied by <context:component-scan>
on all beans registered
in the application context, even for A
which was manually registered in the XML.
但是,如果我们有如下的XML,将我们得到,因为我们已经指定复制豆类都&LT;背景:注解配置/&GT; 和$ C>&LT;背景:组件扫描&GT;
But what if we have the following XML, will we get duplicated beans because we've specified both <context:annotation-config />
and <context:component-scan>
?
<context:annotation-config />
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />
不,不重复,我们再次得到预期的结果:
No, no duplications, We again get the expected result:
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
这是因为这两个标记注册相同的处理工具(&LT;背景:注解配置/&GT;
可如果&LT省略;背景:组件扫描方式&gt;指定
),但春季需要运行这些只有一次照顾
That's because both tags register the same processing tools (<context:annotation-config />
can be omitted if <context:component-scan>
is specified) but Spring takes care of running them only once.
就算你注册多次处理工具自己,春天还是会确保他们完成他们的任务只有一次;这个XML:
Even if you register the processing tools yourself multiple times, Spring will still make sure they do their magic only once; this XML:
<context:annotation-config />
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />
<bean id="bla" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla1" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla2" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla3" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
仍会产生以下结果:
will still generate the following result:
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
确定,大约斥责它。
OK, that about raps it up.
我希望与@Tomasz Nurkiewicz和@Sean帕特里克·弗洛伊德的响应沿着这条信息,你需要了解如何&LT;背景:注解配置&GT;
和&LT;背景:组件扫描&GT;
工作
I hope this information along with the responses from @Tomasz Nurkiewicz and @Sean Patrick Floyd are all you need to understand how
<context:annotation-config>
and <context:component-scan>
work.