Spring 开启Annotation <context:annotation-config> 和 <context:component-scan>诠释及区别

来源:互联网 发布:go高级编程书籍 编辑:程序博客网 时间:2024/06/10 02:40

原文地址:http://www.cnblogs.com/leiOOlei/p/3713989.html

<context:annotation-config> 和 <context:component-scan>的区别

<context:annotation-config> 是用于激活那些已经在spring容器里注册过的bean(无论是通过xml的方式还是通过package sanning的方式)上面的注解。

<context:component-scan>除了具有<context:annotation-config>的功能之外,<context:component-scan>还可以在指定的package下扫描以及注册javabean 。

下面我们通过例子来详细查看他们的区别,有三个class   A,B,C,并且B,C的对象被注入到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;   }}
复制代码

 

在applicationContext.xml中加入下面的配置 :

<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>

 

加载applicationContext.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

OK, 这个结果没什么好说的,就是完全通过xml的方式,不过太过时了,下面通过注解的方式来简化我们的xml配置文件

 

下边看看怎么使用<context:annotation-config>和 <context:component-scan>

首先,我们使用autowire的方式将对象bbb和ccc注入到A中:

复制代码
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;  }}
复制代码

 

然后applicationContext.xml配置文件去除属性<property>就简化为下面的样子了

<bean id="bBean"class="com.xxx.B"/><bean id="cBean"class="com.xxx.C"/><bean id="aBean"class="com.yyy.A"/>

 

当我们加载applicationContext.xml配置文件之后,将得到下面的结果:

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

 

OK, ClassA中显然没有注入属性,结果是错误的的,究竟是因为什么呢?为什么我们的属性没有被注入进去呢?

是因为注解本身并不能够做任何事情,它们只是最基本的组成部分,我们需要能够处理这些注解的处理工具来处理这些注解。

这就是<context:annotation-config> 所做的事情,用于激活那些已经在spring容器里注册过的bean

我们将applicationContext.xml配置文件作如下修改:

<context:annotation-config /><bean id="bBean"class="com.xxx.B"/><bean id="cBean"class="com.xxx.C"/><bean id="aBean"class="com.yyy.A"/>

 

这回,当我们加载applicationContext.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

 

OK, 结果正确了

但是如果我们将代码作如下修改:

复制代码
package com.xxx;import org.springframework.stereotype.Component;@Componentpublic class B {  public B() {    System.out.println("creating bean B: " + this);  }}package com.xxx;import org.springframework.stereotype.Component;@Componentpublic 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;@Componentpublic 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;  }}
复制代码

 

applicationContext.xml配置文件修改为:

<context:annotation-config />

 

当我们加载applicationContext.xml配置文件之后,却没有任何输出,这是为什么呢?

那是因为<context:annotation-config />仅能够在已经在已经注册过的bean上面起作用

对于没有在spring容器中注册的bean,它并不能执行任何操作。

但是不用担心,<context:component-scan>除了具有<context:annotation-config />的功能之外,还具有自动将带有@component,@service,@Repository等注解的对象注册到spring容器中的功能。

我们将applicationContext.xml配置文件作如下修改:

<context:component-scan base-package="com.xxx"/>

当我们加载applicationContext.xml的时候,会得到下面的结果:

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

 

这是什么原因呢?

是因为我们仅仅扫描了com.xxx包及其子包的类,而class  A是在com.yyy包下,所以就扫描不到了

下面我们在applicationContext.xml中把com.yyy也加入进来:

<context:component-scan base-package="com.xxx"/><context:component-scan base-package="com.xxx,com.yyy"/>

 

然后加载applicationContext.xml就会得到下面的结果:

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

 

哇,结果正确啦 !

回头看下我们的applicationContext.xml文件,已经简化为两行context:component-scan了,是不是很简单?

 

那如果我们在applicationContext.xml手动加上下面的配置,

也就是说既在applicationContext.xml中手动的注册了A的实例对象,同时,通过component-scan去扫描并注册B,C的对象,如下

<context:component-scan base-package="com.xxx"/><bean id="aBean"class="com.yyy.A"/>

 

结果仍是正确的:

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

 

虽然class A并不是通过扫描的方式注册到容器中的 ,

但是<context:component-scan> 所产生的的处理那些注解的处理器工具,会处理所有绑定到容器上面的bean,不管是通过xml手动注册的还是通过scanning扫描注册的。

 

那么,如果我们通过下面的方式呢?我们既配置了<context:annotation-config />,又配置了<context:component-scan base-package="com.xxx" />,它们都具有处理在容器中注册的bean里面的注解的功能。会不会出现重复注入的情况呢?

<context:annotation-config /><context:component-scan base-package="com.xxx"/><bean id="aBean"class="com.yyy.A"/>

 

不用担心,不会出现的,结果如下:

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

 

因为<context:annotation-config />和 <context:component-scan>同时存在的时候,前者会被忽略。

也就是那些@autowire,@resource等注入注解只会被注入一次

哪怕是你手动的注册了多个处理器,spring仍然只会处理一次:

复制代码
<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" />
复制代码

结果仍是正确的:

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

阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 涂牙膏把脸烧伤怎么办 月经血排不出来怎么办 猫眼角膜掉了一块怎么办 腰酸痛直不起腰怎么办 白血病移植后复发了怎么办 斐讯k2红灯常亮怎么办 洗衣机把烟洗了怎么办 吸烟吸的恶心想吐怎么办 显示双方信息的明细怎么办 电脑关不了机了怎么办 xp系统关不了机怎么办 灯的开关闭不了怎么办 灯的开关按不动怎么办 灯开关按不动了怎么办 灯的开关摁不动怎么办 微信群500人满了怎么办 作业帮搜不到题目怎么办呢 金融社保卡密码忘了怎么办 工作未完想从国企辞职怎么办 宫腔粘连术后流血多怎么办 宫腔粘连术后一直流血怎么办? cad图框放不下图怎么办 简历假的入职怎么办 脱贫攻坚怎么看怎么办怎么干 吃的下没力气怎么办 恢复留查公示后怎么办 微语简报删了怎么办 小学生未完成作业作为老师怎么办 抽调人员想回原单位怎么办 扫码支付没成功怎么办 成都电表卡丢了怎么办 社保未满15年怎么办 60岁社保没交满15年怎么办 柴油车dpf是亮了怎么办 贴双眼皮贴眼睛肿了怎么办 送孩子赴澳洲家长怎么办签证? 开指过程中发烧怎么办 大水口热流道有料花怎么办 奶奶疼外孙胜过孙子怎么办 吃了有病的鸡怎么办 博士真毕不了业怎么办