Difference between <context:annotation-config> vs <context:component-scan>
我在学习Spring3,我似乎没有掌握
从我读到的内容来看,它们似乎处理不同的注释(@required,@autowired etc vs@component,@repository,@service etc),但从我读到的内容来看,它们注册了相同的bean后处理器类。
更让我困惑的是,
有人能给这些标签上点颜色吗?什么是相似的,什么是不同的,一个被另一个取代,它们互相完善,我需要它们中的一个吗,两者都需要?
我将用一些例子来说明不同/相似之处。好的。
让我们从
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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配置:好的。
1 2 3 4 5 6 | <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> |
加载上下文将生成以下输出:好的。
1 2 3 4 5 | 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 |
好的,这是预期的输出。但这是"老式"的春天。现在我们有了注释,所以让我们使用它们来简化XML。好的。
首先,让我们自动连接bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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中删除以下行:好的。
1 2 | <property name="bbb" ref="bBean" /> <property name="ccc" ref="cBean" /> |
我的XML现在简化为:好的。
1 2 3 | <bean id="bBean" class="com.xxx.B" /> <bean id="cBean" class="com.xxx.C" /> <bean id="aBean" class="com.yyy.A" /> |
当我加载上下文时,得到以下输出:好的。
1 2 3 | creating bean B: com.xxx.B@5e5a50 creating bean C: com.xxx.C@54a328 creating bean A: com.yyy.A@a3d4cf |
好吧,这是错误的!发生了什么事?为什么我的属性没有自动连接?好的。
好吧,注释是一个很好的特性,但是它们本身什么也不做。他们只是做些注解。您需要一个处理工具来查找注释并对它们进行处理。好的。
如果我将XML更改为:好的。
1 2 3 4 | <context:annotation-config /> <bean id="bBean" class="com.xxx.B" /> <bean id="cBean" class="com.xxx.C" /> <bean id="aBean" class="com.yyy.A" /> |
当我加载应用程序上下文时,得到了正确的结果:好的。
1 2 3 4 5 | 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定义,并用注释替换它们:好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 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中,我们只保留以下内容:好的。
1 | <context:annotation-config /> |
我们加载上下文,结果是…没有什么。不会创建bean,也不会自动连接bean。没有什么!好的。
这是因为,正如我在第一段中所说,
但这对
1 | <context:component-scan base-package="com.xxx" /> |
当我加载上下文时,得到以下输出:好的。
1 2 | creating bean B: com.xxx.B@1be0f0a creating bean C: com.xxx.C@80d1ff |
嗯…有东西不见了。为什么?好的。
如果你仔细观察这些类,
为了解决这个问题,我还添加了另一个包:好的。
1 | <context:component-scan base-package="com.xxx,com.yyy" /> |
现在我们得到了预期的结果:好的。
1 2 3 4 5 | 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定义,而是有注释。好的。
最后一个例子是,保留注释类
1 2 | <context:component-scan base-package="com.xxx" /> <bean id="aBean" class="com.yyy.A" /> |
我们仍然得到正确的结果:好的。
1 2 3 4 5 | 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 |
即使没有通过扫描获得类
但是如果我们有以下XML,我们会得到重复的bean吗,因为我们已经指定了
1 2 3 | <context:annotation-config /> <context:component-scan base-package="com.xxx" /> <bean id="aBean" class="com.yyy.A" /> |
不,没有重复,我们再次得到预期结果:好的。
1 2 3 4 5 | 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仍然会确保它们只做一次魔术;此XML:好的。
1 2 3 4 5 6 7 | <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" /> |
仍将生成以下结果:好的。
1 2 3 4 5 | 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的回复都能让你明白
我发现了这个很好的摘要,说明了哪些注释是由哪些声明获取的。通过研究,你会发现
@Component 、@Service 、@Repository 、@Controller 、@Endpoint 。@Configuration 、@Bean 、@Lazy 、@Scope 、@Order 、@Primary 、@Profile 、@DependsOn 、@Import 、@ImportResource 。
正如你所看到的,EDCOX1,0,逻辑上扩展了EDCOX1,1,用类路径组件扫描和Java@配置特征。
弹簧允许你做两件事:
1。自动发电通常在applicationcontext.xml中定义bean,其他bean使用构造函数或setter方法。可以使用XML或注释连接bean。如果使用注释,则需要激活注释,并且必须添加applicationContext.xml中的
对手动XML配置进行转义的一个步骤是
2。自动发现自动发现进一步简化了XML,从某种意义上说,您甚至不需要在applicationcontext.xml中添加
作为结论:
- 为了能够使用@自动连线注释
用于确定搜索具体的bean和自动布线的尝试。
有关更多信息,请阅读:
- 3.9。基于批注的容器配置
- 3.10。类路径扫描和托管组件
两者之间的区别真的很简单!.
1 | <context:annotation-config /> |
使您能够使用仅限于连接bean的属性和构造函数的注释!.
在哪里
1 | <context:component-scan base-package="org.package"/> |
支持
注:扫描
autowired @ @和所需的目标应该是使物业水平指标在国际奥委会在Spring bean使用论文注释。一是要使论文注释include
所需的处理工具提供
注:标注本身没有什么我们需要做的,是加工工具,在A级,负责核心流程。
"库"的服务和"控制器"组件是一流水平,和他们的目标。
这包,找到它
XML注释升级
Spring2.5还添加了对jsr-250注释的支持,如@resource、@postconstruct和@predstroy。使用这些注释还需要在Spring容器中注册某些beanPostProcessor。和往常一样,这些可以注册为单个bean定义,但也可以通过在Spring配置中包含
摘自基于注释的配置的Spring文档
Spring提供了自动检测"构造型"类并在applicationContext中注册相应的bean定义的功能。
根据org.springframework.stereotype的javadoc:
构造型是表示类型或方法在整个体系结构(在概念上,而不是在实现上)中的角色的注释。示例:@controller@service@repository等。这些是工具和方面使用的(成为切入点的理想目标)。
为了自动检测这种"原型"类,需要
1 | <context:annotation-config> |
只解析@autowired和@qualifer注释,也就是说,关于依赖项注入,还有其他的注释做同样的工作,我想@inject是怎么做的,但是都将通过注释解析DI。
注意,即使您已经声明了
- xml:
。 - @注释:@component,@service,@repository,@controller
- javaconfig:@configuration,@bean
现在用
1 | <context:component-scan> |
它有两个功能:
- 它扫描用注释的所有类@组件、@service、@repository、@controller和@configuration并创建bean
- 它和
的工作方式相同。
因此,如果您申报
这一切
例如,一个常见的场景是只通过XML声明bean,并通过注释解析di。
1 2 3 4 | <bean id="serviceBeanA" class="com.something.CarServiceImpl" /> <bean id="serviceBeanB" class="com.something.PersonServiceImpl" /> <bean id="repositoryBeanA" class="com.something.CarRepository" /> <bean id="repositoryBeanB" class="com.something.PersonRepository" /> |
我们只声明了bean,与
1 | <context:component-scan /> implicitly enables <context:annotation-config/> |
尝试使用
这意味着AutoWiredAnnotationBeanPostProcessor将不被启用,Spring容器将不处理AutoWiring注释。
1 2 | <context:annotation-config/> <!-- is used to activate the annotation for beans --> <context:component-scan base-package="x.y.MyClass" /> <!-- is for the Spring IOC container to look for the beans in the base package. --> |
另一个需要注意的重要点是,
总结:
1 2 | <context:annotation-config/> <!-- activates the annotations --> <context:component-scan base-package="x.y.MyClass" /> <!-- activates the annotations + register the beans by looking inside the base-package --> |
作为一个互补使用,你可以使用在
它是在spring.io描述
Configures component scanning directives for use with
@Configuration classes. Provides support parallel with Spring XML's
element.
一个音符的事情,如果你使用Spring配置和启动,@ @ @诱发电可以springbootapplication隐含使用注释。
你可以找到更多的信息在Spring上下文的架构文件。以下是在spring-context-4.3.xsd
1 | <conxtext:annotation-config /> |
1 2 3 4 5 6 7 8 9 | Activates various annotations to be detected in bean classes: Spring's @Required and @Autowired, as well as JSR 250's @PostConstruct, @PreDestroy and @Resource (if available), JAX-WS's @WebServiceRef (if available), EJB 3's @EJB (if available), and JPA's @PersistenceContext and @PersistenceUnit (if available). Alternatively, you may choose to activate the individual BeanPostProcessors for those annotations. Note: This tag does not activate processing of Spring's @Transactional or EJB 3's @TransactionAttribute annotation. Consider the use of the <tx:annotation-driven> tag for that purpose. |
1 | <context:component-scan> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Scans the classpath for annotated components that will be auto-registered as Spring beans. By default, the Spring-provided @Component, @Repository, @Service, @Controller, @RestController, @ControllerAdvice, and @Configuration stereotypes will be detected. Note: This tag implies the effects of the 'annotation-config' tag, activating @Required, @Autowired, @PostConstruct, @PreDestroy, @Resource, @PersistenceContext and @PersistenceUnit annotations in the component classes, which is usually desired for autodetected components (without external configuration). Turn off the 'annotation-config' attribute to deactivate this default behavior, for example in order to use custom BeanPostProcessor definitions for handling those annotations. Note: You may use placeholders in package paths, but only resolved against system properties (analogous to resource paths). A component scan results in new bean definitions being registered; Spring's PropertySourcesPlaceholderConfigurer will apply to those bean definitions just like to regular bean definitions, but it won't apply to the component scan settings themselves. |
这告诉我要跳一跳使用annotated豆豆与那些将有线通
本告诉Spring容器,在开始寻找那些annotated豆。这里的春天要搜索所有子包的库包。
这用于告诉容器我的包中有bean类,扫描这些bean类。为了按bean顶部的容器扫描bean类,我们必须编写如下立体类型注释之一。
江户十一〔15〕、江户十一〔16〕、江户十一〔17〕、江户十一〔18〕。
如果我们不想显式地用XML编写bean标记,那么容器如何知道bean中是否有自动连接。这可以通过使用
一个EDCOX1×0的自定义标签注册了一组bean定义,除了它的主要职责是扫描Java包和从类路径注册bean定义。
如果出于某种原因,要避免注册默认be an定义,那么可以在组件扫描中指定一个附加的"annotation config"属性,方法如下:
1 | <context:component-scan basePackages="" annotation-config="false"/> |
参考文献:http://www.java-allandsundry.com/2012/12/contextcomponent-scan-contextannotation.html