Spring 开启Annotation 和 诠释及区别

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

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

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

下面咱们经过例子来详细查看他们的区别,有三个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中加入下面的配置 :this

<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配置文件,将获得下面的结果:spa

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@1e8a1f63d

OK, 这个结果没什么好说的,就是彻底经过xml的方式,不过太过期了,下面经过注解的方式来简化咱们的xml配置文件code

 

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

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

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;
@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;
  }
}

 

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

相关文章
相关标签/搜索