和 之间的区别和<上下文:组件扫描>
我正在学习 Spring 3
,但我似乎没有掌握
。
从我读到的内容来看,它们似乎处理不同的注释(@Required
、@Autowired
等与@Component
、@Repository
、@Service
等),而且从我读到的内容来看,它们注册了相同的 bean 后处理器 类。
更让我困惑的是,
上有一个 annotation-config
属性。
有人可以解释一下这些标签吗?什么是相似的,什么是不同的,一个被另一个取代了,它们是否相互补充,我需要其中之一还是两者都需要?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
用于激活已在应用程序上下文中注册的 bean 中的注释(无论它们是使用 XML 还是通过包扫描定义的)。
也可以执行
的操作,但
> 还扫描包以在应用程序上下文中查找并注册 bean。我将使用一些例子来展示差异/相似之处。
让我们从
A
、B
和C
类型的三个 Bean 的基本设置开始,其中B
和>C
被注入到A
中。使用以下 XML 配置:
加载上下文会产生以下输出:
好的,这是预期的输出。但这是“旧式”春天。现在我们有了注释,所以让我们使用它们来简化 XML。
首先,让我们自动装配 bean
A
上的bbb
和ccc
属性,如下所示:这允许我从 XML 中删除以下行:
My XML现在简化为:
当我加载上下文时,我得到以下输出:
好的,这是错误的!发生了什么?为什么我的属性没有自动连接?
嗯,注释是一个很好的功能,但它们本身没有任何作用。他们只是注释一些东西。您需要一个处理工具来查找注释并对其进行处理。
来救援。这将激活它在定义其本身的同一应用程序上下文中定义的 bean 上找到的注释的操作。如果我将 XML 更改为:
当我加载应用程序上下文时,我会得到正确的结果:
好的,这很好,但我从 XML 中删除了两行并添加了一行。这并不是很大的区别。使用注释的想法是它应该删除 XML。
因此,让我们删除 XML 定义并将它们全部替换为注释:
而在 XML 中,我们只保留以下内容:
我们加载上下文,结果是...什么也没有。不会创建任何 Bean,也不会自动装配 Bean。没有什么!
这是因为,正如我在第一段中所说,
仅适用于在应用程序上下文中注册的 bean。因为我删除了三个 bean 的 XML 配置,所以没有创建任何 bean,并且
没有要处理的“目标”。但这对于可以扫描包以查找要处理的“目标”的
来说不是问题。让我们将 XML 配置的内容更改为以下条目:当我加载上下文时,我得到以下输出:
嗯...缺少一些东西。为什么?
如果仔细观察这些类,会发现类
A
具有包com.yyy
,但我已在
中指定> 使用包com.xxx
,所以这完全错过了我的A
类,只选择了B
和C
位于com.xxx
包中。为了解决这个问题,我还添加了另一个包:
现在我们得到了预期的结果:
就是这样!现在您不再拥有 XML 定义,而是拥有注释。
作为最后一个示例,保留带注释的类
A
、B
和C
并将以下内容添加到 XML 中,加载后我们会得到什么语境?我们仍然得到正确的结果:
即使没有通过扫描获取类
A
的bean,处理工具仍然由
应用在所有已注册的 bean 上在应用程序上下文中,即使对于在 XML 中手动注册的
A
也是如此。但是,如果我们有以下 XML,我们会得到重复的 bean 吗,因为我们同时指定了< /代码>?
和不,没有重复,我们再次得到了预期的结果:
这是因为两个标签注册了相同的处理工具(如果
)指定了 component-scan>),但 Spring 只负责运行它们一次。即使您自己多次注册处理工具,Spring 仍然会确保它们只发挥其魔力一次;这个 XML:
仍然会生成以下结果:
好的,这就结束了。
我希望这些信息以及 @Tomasz Nurkiewicz 和 @Sean Patrick Floyd 的回复足以让您了解如何
和
有效。<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).<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.
Let's start with a basic setup of three beans of type
A
,B
andC
, withB
andC
being injected intoA
.With the following XML configuration :
Loading the context produces the following output:
OK, this is the expected output. But this is "old style" Spring. Now we have annotations so let's use those to simplify the XML.
First, lets autowire the
bbb
andccc
properties on beanA
like so:This allows me to remove the following rows from the XML:
My XML is now simplified to this:
When I load the context I get the following output:
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.
<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.If I change my XML to this:
when I load the application context I get the proper result:
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.
So let's remove the XML definitions and replace them all with annotations:
While in the XML we only keep this:
We load the context and the result is... Nothing. No beans are created, no beans are autowired. Nothing!
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.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:When I load the context I get the following output:
Hmmmm... something is missing. Why?
If you look closely at the classes, class
A
has packagecom.yyy
but I've specified in the<context:component-scan>
to use packagecom.xxx
so this completely missed myA
class and only picked upB
andC
which are on thecom.xxx
package.To fix this, I add this other package also:
and now we get the expected result:
And that's it! Now you don't have XML definitions anymore, you have annotations.
As a final example, keeping the annotated classes
A
,B
andC
and adding the following to the XML, what will we get after loading the context?We still get the correct result:
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 registeredin the application context, even for
A
which was manually registered in the XML.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>
?No, no duplications, We again get the expected result:
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.Even if you register the processing tools yourself multiple times, Spring will still make sure they do their magic only once; this XML:
will still generate the following result:
OK, that about wraps it up.
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.我发现了这个很好的摘要,其中注释由哪些声明选取。通过研究你会发现
识别
识别的注释的超集,即:@配置
,@Bean
、@Lazy
、@Scope
、@Order
、@Primary
、@Profile
、@DependsOn
、@Import
、@ImportResource
如您所见
>
扩展
具有 CLASSPATH 组件扫描和 Java @Configuration 功能。I found this nice summary of which annotations are picked up by which declarations. By studying it you will find that
<context:component-scan/>
recognizes a superset of annotations recognized by<context:annotation-config/>
, namely:@Component
,@Service
,@Repository
,@Controller
,@Endpoint
@Configuration
,@Bean
,@Lazy
,@Scope
,@Order
,@Primary
,@Profile
,@DependsOn
,@Import
,@ImportResource
As you can see
<context:component-scan/>
logically extends<context:annotation-config/>
with CLASSPATH component scanning and Java @Configuration features.Spring 允许您做两件事:
1。自动装配
通常在applicationContext.xml中定义bean,其他bean使用以下方式连接
构造函数或设置方法。您可以使用 XML 或注释来连接 bean。
如果您使用注释,则需要激活注释并且必须添加
applicationContext.xml 中的
。这将简化applicationContext.xml 中的标记结构,因为您不必手动连接 bean(构造函数或 setter)。您可以使用@Autowire注释,bean将按类型连接。
摆脱手动 XML 配置的一个进步是
2。自动发现
自动发现进一步简化了 XML,从某种意义上说,您甚至不需要在 applicationContext.xml 中添加
标记。您只需使用以下注释之一标记特定的 bean,Spring 就会自动将标记的 bean 及其依赖项连接到 Spring 容器中。注解如下:@Controller、@Service、@Component、@Repository。通过使用
并指向基础包,Spring 将自动发现组件并将其连接到 Spring 容器中。结论:
是为了能够使用@Autowired注解
用于确定搜索特定的bean和自动装配的尝试。
Spring allows you to do two things:
1. Autowiring
Usually in applicationContext.xml you define beans and other beans are wired using
constructor or setter methods. You can wire beans using XML or annotations.
In case you use annotations, you need to activate annotations and you have to add
<context:annotation-config />
in applicationContext.xml. This will simplify thestructure of the tag from applicationContext.xml, because you will not have to manually wire beans (constructor or setter). You can use
@Autowire
annotation and the beans will be wired by type.A step forward for escaping the manual XML configuration is
2. Autodiscovery
Autodiscovery is simplifying the XML one step further, in the sense that you don't even need too add the
<bean>
tag in applicationContext.xml. You just mark the specific beans with one of the following annotation and Spring will automatically wire the marked beans and their dependencies into the Spring container. The annotations are as follow: @Controller, @Service, @Component, @Repository. By using<context:component-scan>
and pointing the base package, Spring will auto-discover and wire the components into Spring container.As a conclusion:
<context:annotation-config />
is used in order to be able to use@Autowired annotation
<context:component-scan />
is used to determine the search ofspecific beans and attempt of autowiring.
激活 bean 中的许多不同注释,无论它们是在 XML 中定义还是通过组件扫描定义。
用于在不使用 XML 的情况下定义 beans有关详细信息,请阅读:
<context:annotation-config>
activates many different annotations in beans, whether they are defined in XML or through component scanning.<context:component-scan>
is for defining beans without using XMLFor further information, read:
: 扫描并激活 spring config xml 中已注册 bean 的注释。
: Bean 注册 +@Autowired 和 @Required< /strong> 是目标属性级别,因此 bean 应该在使用这些注释之前在 Spring IOC 中注册。要启用这些注释,必须注册相应的 bean 或包含
。即
仅适用于已注册的 bean。@Required 启用
RequiredAnnotationBeanPostProcessor
处理工具@Autowired启用
AutowiredAnnotationBeanPostProcessor
处理工具注意:Annotation本身无关,我们需要一个Processing Tool,也就是下面有一个类,负责核心流程。
@Repository、@Service 和 @Controller 是 @Component,它们针对类水平。
它扫描包并查找并注册 bean,它包括
完成的工作。将 XML 迁移到注释
<context:annotation-config>
: Scanning and activating annotations for already registered beans in spring config xml.<context:component-scan>
: Bean registration +<context:annotation-config>
@Autowired and @Required are targets property level so bean should register in spring IOC before use these annotations. To enable these annotations either have to register respective beans or include
<context:annotation-config />
. i.e.<context:annotation-config />
works with registered beans only.@Required enables
RequiredAnnotationBeanPostProcessor
processing tool@Autowired enables
AutowiredAnnotationBeanPostProcessor
processing toolNote: Annotation itself nothing to do, we need a Processing Tool, which is a class underneath, responsible for the core process.
@Repository, @Service and @Controller are @Component, and they targets class level.
<context:component-scan>
it scans the package and find and register the beans, and it includes the work done by<context:annotation-config />
.Migrating XML to Annotations
两者之间的区别真的很简单!
使您能够使用仅限于连接 bean 的属性和构造函数的注释!。
Where as
启用
可以执行的所有操作,并添加使用构造型,例如..@Component
,@Service
、@Repository
。因此,您可以连接整个 bean,而不仅限于构造函数或属性!。The difference between the two is really simple!.
Enables you to use annotations that are restricted to wiring up properties and constructors only of beans!.
Where as
Enables everything that
<context:annotation-config />
can do, with addition of using stereotypes eg..@Component
,@Service
,@Repository
. So you can wire entire beans and not just restricted to constructors or properties!.仅解析
@Autowired
和@Qualifer
注解,仅此而已,关于依赖注入,还有其他做同样工作的注释,我想如何@Inject
,但都是通过注释来解析DI。请注意,即使您已经声明了
元素,您也必须声明您的类如何成为 Bean,请记住我们有三个可用的Now with
它做了两件事:
@Component、@Service、@Repository、@Controller 和 @Configuration 并创建一个 Bean
执行相同的工作。因此,如果您声明
,则不再需要声明
。这就是全部
一个常见的场景是例如通过 XML 只声明一个 bean 并通过注释解析 DI,例如
我们只声明了 bean,没有关于
和< ;property>
,DI通过@Autowired配置在自己的类中。这意味着服务将 @Autowired 用于其存储库组件,而存储库将 @Autowired 用于 JdbcTemplate、DataSource 等组件。Only resolves the
@Autowired
and@Qualifer
annotations, that's all, it about the Dependency Injection, There are other annotations that do the same job, I think how@Inject
, but all about to resolve DI through annotations.Be aware, even when you have declared the
<context:annotation-config>
element, you must declare your class how a Bean anyway, remember we have three available options<bean>
Now with
It does two things:
@Component, @Service, @Repository, @Controller and @Configuration and create a Bean
<context:annotation-config>
does.Therefore if you declare
<context:component-scan>
, is not necessary anymore declare<context:annotation-config>
too.Thats all
A common scenario was for example declare only a bean through XML and resolve the DI through annotations, for example
We have only declared the beans, nothing about
<constructor-arg>
and<property>
, the DI is configured in their own classes through @Autowired. It means the Services use @Autowired for their Repositories components and the Repositories use @Autowired for the JdbcTemplate, DataSource etc..components
标签告诉 Spring 扫描代码库以自动解决包含 @Autowired 注释的类的依赖关系要求。Spring 2.5 还添加了对 JSR-250 注解的支持,例如 @Resource、@PostConstruct 和 @PreDestroy。使用这些注解还需要在 Spring 容器中注册某些 BeanPostProcessor。与往常一样,它们可以注册为单独的 bean 定义,但也可以通过在 spring 配置中包含
标签来隐式注册它们。取自 Spring 文档 基于注释的配置
Spring 提供了以下功能自动检测“构造型”类并向 ApplicationContext 注册相应的 BeanDefinition。
根据org.springframework.stereotype:
构造型是表示类型或方法在整个架构中的角色的注释(在概念层面,而不是实现层面)。
示例:@Controller @Service @Repository 等。
这些旨在供工具和方面使用(成为切入点的理想目标)。
要自动检测此类“构造型”类,需要
标记。
标记还告诉 Spring 扫描指定包(及其所有子包)下的可注入 bean 的代码。The
<context:annotation-config>
tag tells Spring to scan the codebase for automatically resolving dependency requirements of the classes containing @Autowired annotation.Spring 2.5 also adds support for JSR-250 annotations such as @Resource, @PostConstruct, and @PreDestroy.Use of these annotations also requires that certain BeanPostProcessors be registered within the Spring container. As always, these can be registered as individual bean definitions, but they can also be implicitly registered by including
<context:annotation-config>
tag in spring configuration.Taken from Spring documentation of Annotation Based Configuration
Spring provides the capability of automatically detecting 'stereotyped' classes and registering corresponding BeanDefinitions with the ApplicationContext.
According to javadoc of org.springframework.stereotype:
Stereotypes are Annotations denoting the roles of types or methods in the overall architecture (at a conceptual, rather than implementation, level).
Example: @Controller @Service @Repository etc.
These are intended for use by tools and aspects (making an ideal target for pointcuts).
To autodetect such 'stereotype' classes,
<context:component-scan>
tag is required.The
<context:component-scan>
tag also tells Spring to scan the code for injectable beans under the package (and all its subpackages) specified.尝试在您的配置中使用
@Service, @Repository, @Component 工作正常,但 @Autowired、@Resource 和 @Inject 不起作用。这意味着 AutowiredAnnotationBeanPostProcessor 将不会启用,Spring 容器将不会处理自动装配注释。
try with
<context:component-scan base-package="..." annotation-config="false"/>
, in your configuration @Service, @Repository, @Component works fine, but @Autowired,@Resource and @Inject doesn't work.This means AutowiredAnnotationBeanPostProcessor will not be enabled and Spring container will not process the Autowiring annotations.
另一个需要注意的要点是,
context:component-scan
隐式调用context:annotation-config
来激活 bean 上的注释。如果您不希望 context:component-scan 为您隐式激活注释,您可以继续设置 context:component-scan 的annotation-config 元素为假
。总结一下:
The other important point to note is that
context:component-scan
implicitly calls thecontext:annotation-config
to activate the annotations on beans. Well if you don't wantcontext:component-scan
to implicitly activate annotations for you, you can go on setting the annotation-config element of thecontext:component-scan
tofalse
.To summarize:
:这个是用来告诉容器我的包里有bean类,扫描这些bean类。为了通过 bean 顶部的容器扫描 bean 类,我们必须编写如下所示的立体类型注释之一。
@Component
、@Service
、@Repository
、@Controller
:如果我们不想在 XML 中显式编写 bean 标签,那么容器如何知道 bean 中是否存在自动装配。这可以通过使用 @Autowired 注释来实现。我们必须通过 context:annotation-config 通知容器我的 bean 中有自动装配。
<context:component-scan base-package="package name" />
:This is used to tell the container that there are bean classes in my package scan those bean classes. In order to scan bean classes by container on top of the bean we have to write one of the stereo type annotation like following.
@Component
,@Service
,@Repository
,@Controller
<context:annotation-config />
:If we don't want to write bean tag explicitly in XML then how the container knows if there is a auto wiring in the bean. This is possible by using
@Autowired
annotation. we have to inform to the container that there is auto wiring in my bean bycontext:annotation-config
.
自定义标记除了扫描 java 包并从类路径注册 bean 定义的主要职责之外,还注册与 相同的一组 bean 定义。如果由于某种原因要避免注册默认 bean 定义,则方法是在组件扫描中指定附加的“annotation-config”属性,如下所示:
参考:
http://www.java-allandsundry.com/2012/12 /contextcomponent-scan-contextannotation.html
A
<context:component-scan/>
custom tag registers the same set of bean definitions as is done by , apart from its primary responsibility of scanning the java packages and registering bean definitions from the classpath.If for some reason this registration of default bean definitions are to be avoided, the way to do that is to specify an additional "annotation-config" attribute in component-scan, this way:
Reference:
http://www.java-allandsundry.com/2012/12/contextcomponent-scan-contextannotation.html
:这告诉Spring我将使用带注释的bean作为spring bean,并且这些bean将通过
@Autowired
注释连接,而不是声明在 spring 配置 xml 文件中。
:这告诉 Spring 容器从哪里开始搜索那些带注释的 bean。这里spring会搜索基础包的所有子包。
<context:annotation-config>
:This tells Spring that I am going to use Annotated beans as spring bean and those would be wired through
@Autowired
annotation, instead of declaring in spring config xml file.<context:component-scan base-package="com.test...">
:This tells Spring container, where to start searching those annotated beans. Here spring will search all sub packages of the base package.
您可以在 spring 上下文架构文件中找到更多信息。
以下是 spring-context-4.3.xsd
you can find more information in spring context schema file.
following is in spring-context-4.3.xsd
作为补充,您可以使用
@ComponentScan
以注释的方式使用
。它也在 中进行了描述spring.io
需要注意的一件事是,如果您使用 Spring Boot,则可以通过使用 @SpringBootApplication 注解来隐含 @Configuration 和 @ComponentScan。
As a complementary, you can use
@ComponentScan
to use<context:component-scan>
in annotation way.It's also described at spring.io
One thing to note, if you're using Spring Boot, the @Configuration and @ComponentScan can be implied by using @SpringBootApplication annotation.