原文地址:http://techidiocy.com/annotation-config-vs-component-scan-spring-core/

<context:annotation-config> and <context:component-scan> are two of the most basic concepts available in the Spring Core introduced in Spring 3 that every Spring user should understand.It is important that to understand the usage of each of them and how they are different to each other.

annotation-config :  Annotation config main job is to activate all the annotations that are present in java beans and those are already registered either by defining in your application context file or being registered while component scanning. Important point is they need to be registered.

component-scan : Component scan can do everything that annotation config does , in addition to it it also registers the java classes as spring bean those are annotated with @Component , @Service ,@Repository etc.

Let’s see an example that can clear the difference in annotation-config vs component-scan in much more simpler way –
I have three java classes that I have declared in my application context.
SuperUser.java:

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
package com.lotusmedia.typesuper;
 
import com.lotusmedia.typenormal.NormalUser;
import com.lotusmedia.typenormal.TempUser;
 
public class SuperUser {
 
    private NormalUser normalUser;
    private TempUser tempUser;
 
    public SuperUser(){
        System.out.println("Super User Created ->"+this);
    }
 
    public void setNormalUser(NormalUser normalUser) {
        System.out.println("Setting Normal User ->"+normalUser);
        this.normalUser = normalUser;
    }
 
    public void setTempUser(TempUser tempUser) {
        System.out.println("Setting Temp User ->"+tempUser);
        this.tempUser = tempUser;
    }
 
}

NormalUser.java :

1
2
3
4
5
6
7
8
package com.lotusmedia.typenormal;
 
public class NormalUser {
 
    public NormalUser(){
        System.out.println("Normal User Created->"+this);
    }
}

TempUser.java :

1
2
3
4
5
6
7
8
package com.lotusmedia.typenormal;
 
public class TempUser {
 
    public TempUser(){
        System.out.println("Temporary User Created->"+this);
    }
}

Now here is my application context file where I am injecting normalUser and TempUser into SuperUser.
applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    xsi:schemaLocation="
       ">
 
 <bean id="normalUser" class="com.lotusmedia.typenormal.NormalUser"></bean>
 <bean id="tempUser" class="com.lotusmedia.typenormal.TempUser"></bean>
 
 <bean id="superUser" class="com.lotusmedia.typesuper.SuperUser">
    <property name="normalUser" ref="normalUser"></property>
    <property name="tempUser" ref="tempUser"></property>
 </bean>
 
</beans>

And here is the executor class.
Executor.java :

1
2
3
4
5
6
7
8
9
10
11
package com.lotusmedia.run;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class Executor {
 
    public static void main(String args[]){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    }
}

Now when I executed this program I got output like this in my console and it is what we were expecting.

1
2
3
4
5
Normal User Created->com.lotusmedia.typenormal.NormalUser@75e845c2
Temporary User Created->com.lotusmedia.typenormal.TempUser@1cec6b00
Super User Created ->com.lotusmedia.typesuper.SuperUser@6564dbd5
Setting Normal User ->com.lotusmedia.typenormal.NormalUser@75e845c2
Setting Temp User ->com.lotusmedia.typenormal.TempUser@1cec6b00

Till now everything is good and as expected. Now lets do some modifications and introduce annotations in our beans. So , I have modified SuperUser.java to use annotations for wiring the properties.(notice the autowired annotation).

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
package com.lotusmedia.typesuper;
 
import org.springframework.beans.factory.annotation.Autowired;
 
import com.lotusmedia.typenormal.NormalUser;
import com.lotusmedia.typenormal.TempUser;
 
public class SuperUser {
 
    private NormalUser normalUser;
    private TempUser tempUser;
 
    public SuperUser(){
        System.out.println("Super User Created ->"+this);
    }
        @Autowired
    public void setNormalUser(NormalUser normalUser) {
        System.out.println("Setting Normal User ->"+normalUser);
        this.normalUser = normalUser;
    }
        @Autowired
    public void setTempUser(TempUser tempUser) {
        System.out.println("Setting Temp User ->"+tempUser);
        this.tempUser = tempUser;
    }
 
}

And from configuration file I have removed the properties injection, so now my context file looks like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    xsi:schemaLocation="
       ">
 
 <bean id="normalUser" class="com.lotusmedia.typenormal.NormalUser"></bean>
 <bean id="tempUser" class="com.lotusmedia.typenormal.TempUser"></bean>
 
 <bean id="superUser" class="com.lotusmedia.typesuper.SuperUser"></bean>
 
</beans>

Now I have executed my Executor class again and here is the output.

1
2
3
Normal User Created->com.lotusmedia.typenormal.NormalUser@4cc39a20
Temporary User Created->com.lotusmedia.typenormal.TempUser@485fcf29
Super User Created ->com.lotusmedia.typesuper.SuperUser@a19b1de

This time you will see that properties injection didn’t take place only the new beans were created, now you might be wondering why it didn’t happen as we had marked those properties with the Autowired annotation. So, here is answer , in spring by default annotations don’t do anything by themselves , if you want to use them you have to enable them in your application.
Now enabling annotations in spring is very simple and you have to add only one line of code in your context file to enable them and here is the magic line.

1
<context:annotation-config/>

Updated applicationContext file :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    xsi:schemaLocation="
       ">
 
 <context:annotation-config/>
 <bean id="normalUser" class="com.lotusmedia.typenormal.NormalUser"></bean>
 <bean id="tempUser" class="com.lotusmedia.typenormal.TempUser"></bean>
 
 <bean id="superUser" class="com.lotusmedia.typesuper.SuperUser"></bean>
 
</beans>

Now this time when I executed the Executor class again , below is the output that I got and this is what we were expecting.

1
2
3
4
5
Normal User Created->com.lotusmedia.typenormal.NormalUser@679bfb30
Temporary User Created->com.lotusmedia.typenormal.TempUser@7977b9b
Super User Created ->com.lotusmedia.typesuper.SuperUser@37fd6bea
Setting Normal User ->com.lotusmedia.typenormal.NormalUser@679bfb30
Setting Temp User ->com.lotusmedia.typenormal.TempUser@7977b9b

So,till now all good, let’s play more now I am going to remove the bean declarations from the Xml file and use @Component annotation to register it as a bean.Here are the updated files.
applicationContext.xml :

1
2
3
4
5
6
7
8
9
10
11
12

SuperUser.java : (notice the @Component annotation)

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
package com.lotusmedia.typesuper;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
import com.lotusmedia.typenormal.NormalUser;
import com.lotusmedia.typenormal.TempUser;
@Component
public class SuperUser {
 
    private NormalUser normalUser;
 
    private TempUser tempUser;
 
    public SuperUser(){
        System.out.println("Super User Created ->"+this);
    }
 
    @Autowired
    public void setNormalUser(NormalUser normalUser) {
        System.out.println("Setting Normal User ->"+normalUser);
        this.normalUser = normalUser;
    }
 
    @Autowired
    public void setTempUser(TempUser tempUser) {
        System.out.println("Setting Temp User ->"+tempUser);
        this.tempUser = tempUser;
    }
 
}

NormalUser.java :

1
2
3
4
5
6
7
8
9
10
11
package com.lotusmedia.typenormal;
 
import org.springframework.stereotype.Component;
 
@Component
public class NormalUser {
 
    public NormalUser(){
        System.out.println("Normal User Created->"+this);
    }
}

TempUser.java :

1
2
3
4
5
6
7
8
9
10
11
package com.lotusmedia.typenormal;
 
import org.springframework.stereotype.Component;
 
@Component
public class TempUser {
 
    public TempUser(){
        System.out.println("Temporary User Created->"+this);
    }
}

Now when I executed my Executor class again , this time nothing happened no new bean has been created and no properties has been injected. This is what we were expecting right ? as annotation-config is not suffice and can’t register beans marked with @Component annotation. So , here comes the component scan in play , what it will do , it will scan all the packages provided as an argument to it and will register all the beans marked @Component annotation , and once the bean is registered it annotation-config will inject them.

Now you might be thinking why we need annotation-config when we already have component-scan in our context file ,yes you are thinking in right dierction, as I have already said that component scan can do everything what annotation config does.So, we can safely remove annotation-config from our configuration file and can add component-scan there. So. here is my updated applicationContext file.

1
2
3
4
5
6
7
8
9
10
11
12
    xsi:schemaLocation="
       ">
 
     <context:component-scan base-package="com.lotusmedia.typenormal,com.lotusmedia.typesuper"/> 
</beans>

Now when i executed my Executor class again I got the below mentioned output as we were expecting , all the 3 beans have been created and been injected properly.

1
2
3
4
5
Super User Created ->com.lotusmedia.typesuper.SuperUser@426295eb
Normal User Created->com.lotusmedia.typenormal.NormalUser@207f5580
Setting Normal User ->com.lotusmedia.typenormal.NormalUser@207f5580
Temporary User Created->com.lotusmedia.typenormal.TempUser@4f4db0e3
Setting Temp User ->com.lotusmedia.typenormal.TempUser@4f4db0e3

I hope this example has clarified most of the confusion between annotation-config vs component-scan , if you still have any doubt/question please feel free to drop me a comment, I will be more than happy to answer you.

annotation-config vs component-scan – Spring Core--转的更多相关文章

  1. [Spring Boot] Use Component Scan to scan for Bean

    Component Scan is important concept when we want to create Bean. Currently we know what, for the cla ...

  2. spring core:@AliasFor的派生性

    spring对Annotation的派生性应用可谓炉火纯青,在spring core:@Component的派生性讲过支持层次上派生性,而属性上派生的需求则借助了@AliasFor,它是从spring ...

  3. 【Spring开发】—— Spring Core

    原文:[Spring开发]-- Spring Core 前言 最近由于一些工作的需要,还有自己知识的匮乏再次翻开spring.正好整理了一下相关的知识,弥补了之前对spring的一些错误认知.这一次学 ...

  4. vs2012+Spring.Core.dll

    Ⅰ.Spring的点点滴滴--序章   spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架 .net篇(环境为vs2012+Spring.Core.dll) 新建一个控制台 u ...

  5. 多个IoC容器适配器设计及性能测试(Castle.Windsor Autofac Spring.Core)

    [转]多个IoC容器适配器设计及性能测试和容器选择 1. 采用的IoC容器和版本 Autofac.2.6.3.862 Castle.Windsor.3.1.0 Spring.Core.2.0.0 2. ...

  6. spring core 与 context理解

    Spring core是核心层,拥有这BeanFactory这个强大的工厂,是所有bean的管理器: 而spring context是上下文运行环境,基于spring core之上的一个架构, 它之上 ...

  7. Spring core resourc层结构体系及JDK与Spring对classpath中资源的获取方式及结果对比

    1. Spring core resourc层结构体系 1.1. Resource相关结构体系 1.2. ResourceLoader相关体系 2. JDK与Spring对classpath中资源的获 ...

  8. Spring ---annotation (重点)--Resource, Component 重要!!!

    beans.xml: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="ht ...

  9. @EnableAsync annotation metadata was not injected Spring容器启动后访问Servlet报错

    @EnableAsync annotation metadata was not injected 2015年12月20日 20:06:54 7570 在初始化spring事务部分碰到该错误, 详细错 ...

  10. Spring core注解

    1.@Autowired Autowired是用在JavaBean中的注解,通过byType形式,用来给指定的字段或方法注入所需的外部资源 Autowired注解来指定自动装配,可以修饰setter方 ...

随机推荐

  1. 装个蒜。学习下dispatch queue

    dispatch queue的真髓:能串行,能并行,能同步,能异步以及共享同一个线程池. 接口: GCD是基于C语言的APT.虽然最新的系统版本中GCD对象已经转成了Objective-C对象,但AP ...

  2. NYOJ 536 开心的mdd(DP)

    开心的mdd 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 himdd有一天闲着无聊,随手拿了一本书,随手翻到一页,上面描述了一个神奇的问题,貌似是一个和矩阵有关的 ...

  3. Python 之 super & MRO (没有遇到过适用场景)

    WOW!!! 这里wow的是真尼玛绕且没看完, 好困呐,贴上网址,等自己英文好一点再看(https://rhettinger.wordpress.com/2011/05/26/super-consid ...

  4. 如何让MVC6在IIS上面跑

    asp.net5的MVC6发布出来的结果和MVC5之前版本的相差太远了,直接在本地的IIS服务器上面是不可能运行的. 看了汤姆大叔的MVC6项目发布与部署,讲了很多丰富的知识点.但是对于立即要解决问题 ...

  5. JAVA学习博客---2015-8

    八月份的学习博客,今天已经是九月四号了,补上吧.现在我又回到C++了,JAVA的基本的东西都懂了,但是更好的掌握JAVA,我必须原路返回去学习C++,当初为了更快的学JAVA,其实我得C++都是跳着看 ...

  6. [原创]cocos2dx加载网络图片&异步加载图片

    [动机] 之前看到一款卡牌游戏,当你要看全屏高清卡牌的时候,游戏会单独从网络上下载,本地只存了非高清的,这样可以省点包大小,所以我萌生了实现一个读取网络图片的类. [联想] 之前浏览网页的时候经常看到 ...

  7. linux系统添加硬盘方法

    [root@wen /]# fdisk -l[root@wen /]# fdisk /dev/sdb[root@wen /]# mkfs -t ext3 -c /dev/sdb1[root@wen / ...

  8. 收录.NET跨平台及跨数据库的博文...

    本帖,将持续收录.NET跨平台及跨数据库的博文... VS2012+EF6+Mysql配置心路历程: http://www.cnblogs.com/gameman/p/3773240.html ASP ...

  9. java提高篇(十五)-----关键字final

    在程序设计中,我们有时可能希望某些数据是不能够改变的,这个时候final就有用武之地了.final是java的关键字,它所表示的是“这部分是无法修改的”.不想被改变的原因有两个:效率.设计.使用到fi ...

  10. 使用抓包工具SpyNet对你的网络进行监控

    步骤1:下载并安装SpyNet Sniffer嗅探器之后,第一次运行SpyNet Sniffer后,将会弹出[Settings(设置)]对话框,在其中选择需要监听对象,如图所示. 步骤2:单击[Act ...