在前面的大部分例子我们使用XML去指明配置数据去定义在Spring容器中的每一个BeanDefinition。上一节我们展示了如何在

代码层注解的方式来提供大量的配置信息。即使在这些例子中,但是,基础的Bean定义显示定义在XML文件中,与此同时注解

只是驱动了依赖注入。这节提供了一个选择去通过扫描classpath的方式来发现候选的组件Bean。候选的组件匹配了过滤器条

件的那些类并且有一个一致的Bean定义注册在容器中。这个就可以免除了使用XML去展示Bean注册,取而代之的是你可以使用

注解,Aspect类型表达式或者你自定义的过滤器条件去选择注册在容器中的有Bean定义的类。

注意:从Spring3.0开始,许多通过Spring JavaConfig工厂提供的功能是核心Spring框架的部分。这个允许你去定义Bean
使用java而不是使用传统的XML文件。来看下 @Configuration, @Bean, @Import,和 @DependsOn注解的例子,以及如
何使用这些功能。

@Component 和 更多的被沿用的注解

@Repository注解标记那些满足持久层(DAO)的角色的类。Spring 提供了更多的沿用的注解:@Component, @Service, 和

@Controller。@Component是一个对所有的Spring管理的组件的泛型的沿用。 @Repository, @Service,和 @Controller是@Component

的具体化。例如,相对应的在持久层,service层和表示层相。因此,你可以注解你的的组件类使用@Component注解,但是通过

@Repository, @Service, 或者@Controller 你的类在通过共建或者和切面相联系时或更加适配些。@Repository, @Service,和

@Controller 也可能携带额外的寓意在将来的Spring框架的发布版本中。因此,如果你在为你的service层的@Componentor或者 @Service

之间选择时,@Service是一个更好的选择。类似的是,正如上面所说的那样, @Repository已经支持作为一个标记在你持久层是一个

原子一事务。

元注解(Meta-annotatioins)

许多通过Spring提供的注解能够在你的代码中用作元注解。一个元注解就是一个简单地 注解,只不过它可以用在另外的一个注解上面。

例如,上面提到@Service注解就是一个一个拥有@Component主机的元注解:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component // Spring will see this and treat @Service in the same way as @Component
public @interfaceService {
// ....
}

元注解能够组合在一起来创建组合注解。例如,Spring MVC的@RestController注解就是@Controller和@ResponseBody组合。

带有要给value(),元注解类型可以重新声明属性允许用户自定义。这个在想只是暴露源注解属性的一个子集时是很有用的。例如,下面就是

一个定义了session作用的自定义@Scope注解,但是它仍然允许自定义proxyMode。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Scope("session")
public @interfaceSessionScope {
ScopedProxyMode proxyMode() defaultScopedProxyMode.DEFAULT
}

自动发现类并且注册Bean定义

Spring 能够自动发现模式化的类并且使用ApplicationContext中注册相关的BeanDefination。例如,下面的类就能够被自动发现:

    @Service
public classSimpleMovieLister {
privateMovieFinder movieFinder;
@Autowired
publicSimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
@Repository
public classJpaMovieFinder implementsMovieFinder {
// implementation elided for clarity
}

为了自动发现这些类,并且注册相应的Bean,你需要在XML中包括下面的元素,base-package元素师两个类的父包。

    <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="org.example"/>
</beans>
建议:<context:component-scan>的使用就隐式的使用了<context:annotation-config>的功能。所以在使用
<context:component-scan>的时候必要使用<context:annotation-config>。 注意:classpath包的扫描需要相一致的目录路径在classpath中。当你使用ANT构建 JARS时,确保你使用文件时不只
是选择 JAR 任务的方式。

还有,AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor在你使用组件扫描元素的时候就被包括进来了。这

意味着这两个组件自动发现和装配在一起,而不用任何XML中的Bean的配置数据信息。

注意:你可以不适用CommonAnnotationBeanPostProcessorare和AutowiredAnnotationBeanPostProcessor的注册通过
annotation-config的属性值FALSE。

使用过滤器自定义扫描

默认情况下,使用@Component, @Repository, @Service, @Controller或者一个自定义的注解标注的类只发现候选的组件。

但是,你可以修改和扩展这个行为通过应用自定义的过滤器。每一个过滤去元素需要type和expression属性。下面的表格表示

了可选的过滤器:

过滤器类型 例子表达式 描述
annotation(默认情况下) org.example.SomeAnnotation 在目标遵纪按在类型级别使用注解
assignable 一个目标组件可以分配的类
aspectj org.example..*Service+ 一个通过目标组件匹配的AspectJ类型的表达式
regex org\.example\.Default.* 一个通过目标组件类名匹配的正则表达式
custom org.example.MyTypeFilter 实现了org.springframework.core.type .TypeFilter接口的自定义实现

下面的例子表明了基于XML的配置忽略了所有的@Repository注解并且使用stub repositories代替。

<beans>
<context:component-scan base-package="org.example">
<context:include-filter type="regex"
expression=".*Stub.*Repository"/>
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
</beans>
注意:你可以通过提供  use-default-filters="false"作为<component-scan/>元素的属性来是默认
的过滤器失效。这个讲影响自动发现注解类@Component, @Repository, @Service, 或者 @Controller。

在组件内部定义Bean 元数据

Spring 组件也可以像容器提供Bean定义元数据。你可以通过用在@Configuration 主机的类的定义Bean元数据

的@Bean注解来做这件事。下面是一个简单例子:

@Component
public classFactoryMethodComponent {
@Bean
@Qualifier("public")
publicTestBean publicInstance() {
return new TestBean("publicInstance");
}
public void doWork() {
// Component method implementation omitted
}
}

这个类是一个在他的doWork()方法中含有应用代码的Spring组件。但是,它也有助于有一个执行方法publicInstance()

的工厂方法的Bean定义。@Bean注解标明了这个工厂方法和其他Bean定义属性,例如,通过@Qulifier注解的限定符的值。

其他的方法级别的注解能够给通过@Scope @Lazy和自定义的限定符注解指明。

注意:除了它的组件初始化的角色,@Lazy注解还可以 放置标记了在@Autowiredor @Inject的注入点。在这个上下文

中,它会产生一个lazy-resolution代理的注入。

自动装配的域和方法通过额外支持正对自动装配的@Bean方法是支持的:

@Component
public classFactoryMethodComponent {
private static inti;
@Bean
@Qualifier("public")
publicTestBean publicInstance() {
return newTestBean("publicInstance");
}
// use of a custom qualifier and autowiring of method parameters
@Bean
protectedTestBean protectedInstance(
@Qualifier("public")TestBean spouse,
@Value("#{privateInstance.age}")String country) {
TestBean tb = newTestBean("protectedInstance", 1);
tb.setSpouse(tb);
tb.setCountry(country);
returntb;
}
@Bean
@Scope(BeanDefinition.SCOPE_SINGLETON)
privateTestBean privateInstance() {
return newTestBean("privateInstance", i++);
}
@Bean
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode =ScopedProxyMode.TARGET_CLASS)
publicTestBean requestScopedInstance() {
return newTestBean("requestScopedInstance", 3);
}
}

这个例子自动装配了String的方法参数 country到名字为privateInstance的其他Bean的属性Age中。一个Spring表达式语言元素

定义了这个属性的值通过符号 #{ }。对于@Value注解,在解析表达式文本的时候一个表达式解析器被提前配置

去查看Bean的名字。

在Spring组件中@Bean方法相比在Spring @Configuration类中的他们副本处理时不一样的。不同之处在于@Component类没有使用CGLIB

增强去拦截方法和域的调用。CGLIB代理通过调用在@Configuration类的@Bean方法来调用方法和域的来创建Bean元数据引用到相关的对象;

这样的方法不会被一般的Java所调用。行成对比的是,在一个@Component类的内部的@Bean方法中调用一个方法或者域是有标准的Java语法的。

命名自动发现的组件

当一个组件在扫描过程中被自动发现了,它的Bean名字是通过扫描器的BeanNameGenerator策略来生成的。默认情况下,任何模式化的注解(

@Component, @Repository, @Service, 和 @Controller)都可以包含一个name的值,这个值将提供给相应的Bean定义的。如果这样的注解

没有包含了一个name的值,默认的Bean 名字生成器返回了不是大写的非限定的类名。例如,下面的两个组件被发现了,他们名字僵尸myMovieLister和

movieFinderImpl:

@Service("myMovieLister")
public classSimpleMovieLister {
// ...
}
@Repository
public classMovieFinderImpl implementsMovieFinder {
// ...
}
注意:如果你不想依赖默认的Bean 名字策略,你可以提供ige自定义的Bean-name策略。首先你需要实现 BeanNameGenerator接口,并且确保
包括一个默认的空的构造函数。然后在配置扫描器的时候提供完整的限定符的类名:
<beans>
<context:component-scan base-package="org.example"
name-generator="org.example.MyNameGenerator"/>
</beans>

作为一般的规则,考虑指明注解的名字因为在任何时候其他的组件可能显示的引用它。在另一方面,自动生成的名字是足够用的在任何时候容器负责装配。

为自动发现的组件提供一个作用域

一般来讲对于Spring管理的组件,默认的和大部分的作用域对于需要自动发现的组件都是单例的。但是,有时候你需要其他的作用域,这个在Spring2.5中

提供一个新的@Scope注解。简单的在注解的内部提供了作用域的名字:

@Scope("prototype")
@Repository
public classMovieFinderImpl implementsMovieFinder {
// ...
}
注意:为了提供一个自动以的作用域策略而不是依赖基于注解的方式,需要实现ScopeMetadataResolver接口,并且确信包括一个空的构造函数。然后
在配置扫描器的时候提供一个完整的限定符的类名: ```xml
<beans>
<context:component-scan base-package="org.example"
scope-resolver="org.example.MyScopeResolver"/>
</beans>
```

当使用确定的非单例的作用域时,为作用域的对象生成代理可能是必要的。为了这个目的,一个scoped-proxy属性就需要了在组件扫描元素中。三种可能的值

是:no,inferfaces 和targetClass.例如,下面的配置将导致标准的JDK动态代理:

<beans>
<context:component-scan base-package="org.example"
scoped-proxy="interfaces"/>
</beans>

使用注解提供限定符元数据

@Qualifier注解是“使用限定符的细粒度的机遇注解的自动装配”部分讲过了。里面有一个例子展示了 @Qualifier注解的使用,并且在解析自动装配候选的时候

自定义限定符注解去提供细粒度的控制。因为这些例子是在基于XML的Bean定义中的,限定符元数据通过使用在XML中的

的子元素qualifier或者meta提供在候选的Bean定义中。当使用classpath扫描来自动发现组件,你可以再候选的类中提供限定符元数据给类型级别的注解。下面就

是这个知识点的上那个例子:

  @Component
@Qualifier("Action")
public classActionMovieCatalog implementsMovieCatalog {
// ...
}
@Component
@Genre("Action")
public classActionMovieCatalog implementsMovieCatalog {
// ...
}
  @Component
@Offline
public classCachingMovieCatalog implementsMovieCatalog {}
注意:对于大部分的基于注解的可选项,记住注解元数据是和类定义自己绑定的,当XML的使用允许多个相同类型的Bean去igong在他们限定符元数据中的差异,
因为那样的元数据是按实力来提供而不是按类来提供的。

Spring IOC之Classpath扫描和管理的组件的更多相关文章

  1. Spring Framework 学习笔记——核心技术之Spring IOC

    Spring Framework 官网文档学习笔记--核心技术之Spring IOC 官方文档 spring-framework-5.3.9 1. Spring Framework 核心技术 1.1 ...

  2. Spring IoC入门

    ------------------siwuxie095                                 Spring IoC 环境搭建         1.先下载相关库文件,下载链接 ...

  3. 【Java面试】介绍下Spring IoC的工作流程

    Hi,我是Mic 一个工作了4年的粉丝,在面试的时候遇到一个这样的问题. "介绍一下Spring IOC的工作流程" 他说回答得不是很好,希望我能帮他梳理一下. 关于这个问题,我们 ...

  4. Spring核心技术(九)——Spring管理的组件和Classpath扫描

    Spring管理的组件和Classpath的扫描 在前文描述中使用到的Spring中的Bean的定义,都是通过指定的XML来配置的.而前文中描述的注解的解析则是在源代码级别来提供配置元数据的.在那些例 ...

  5. Spring学习笔记之 Spring IOC容器(二) 之注入参数值,自动组件扫描方式,控制Bean实例化方式,使用注解方式

     本节主要内容:    1. 给MessageBean注入参数值    2. 测试Spring自动组件扫描方式    3. 如何控制ExampleBean实例化方式    4. 使用注解方式重构Jdb ...

  6. Spring IOC基础回顾 — 组件扫描和装配

    目录 注解形式配置应用IOC 1. 组件自动扫描 2. 组件依赖:为bean添加注解,实现自动注入 3. Spring IOC应用小结 注解形式配置应用IOC 在类定义.方法定义.成员变量定义前使用, ...

  7. Spring IoC 源码分析 (基于注解) 之 包扫描

    在上篇文章Spring IoC 源码分析 (基于注解) 一我们分析到,我们通过AnnotationConfigApplicationContext类传入一个包路径启动Spring之后,会首先初始化包扫 ...

  8. 谈谈Spring的IoC之注解扫描

    问题   IoC是Inversion of Control的缩写,翻译过来即"控制反转".IoC可以说是Spring的灵魂,想要读懂Spring,必先读懂IoC.不过有时候硬着头皮 ...

  9. Spring IOC(二)beanName 别名管理

    Spring IOC(二)beanName 别名管理 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 一.AliasReg ...

随机推荐

  1. springmvc 接收对象 滴灌摘要

    js 对象 该阵列看起来像 我明白http://blog.csdn.net/baicp3/article/details/12752255本文 我们指示样品棒 data3一个js对象.遗嘱java当代 ...

  2. JUnit实战(1) - JUnit起步(Parameterized参数化测试)

    创建Java Project项目,项目名称:ch01-jumpstart Calculator.java public class Calculator { public double add(dou ...

  3. WebAPI上传大文件

    今天在研究WebAPI的上传与下载,作为Rest的框架,更多是面向资源,就其本身来说,是不会涉及也不应该涉及到大文件的处理,具体多大呢,也就是ASP.NET的限值2G. ASP.NET的pipelin ...

  4. 机器人操作系统 除了Android还有一个ROS(转)

    你知道市面上的机器人都采用了哪些操作系统吗? 估计大多数人给出的答案就是 Android 了.从市面上的产品来看,基于 Android 系统开发的机器人确实是主流,但是还有一种操作系统却鲜为人知,它叫 ...

  5. (大数据工程师学习路径)第三步 Git Community Book----Git介绍

    一.git诞生 同生活中的许多伟大事件一样,Git 诞生于一个极富纷争大举创新的年代.1991年,Linus创建了开源的Linux,并且有着为数众多的参与者.虽然有世界各地的志愿者为Linux编写代码 ...

  6. adb这点小事——远程adb调试

    欢迎转载.转载请注明:http://blog.csdn.net/zhgxhuaa 1.   前言 1.1.  写在前面的话 在之前的一篇文章<360电视助手实现研究>中介绍了在局域网内直接 ...

  7. NYOJ353 3D dungeon 【BFS】

    3D dungeon 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描写叙述 You are trapped in a 3D dungeon and need to find ...

  8. PL/SQL程序中调用Java代码(转)

    主要是学习PL/SQL调用JAVA的方法. 平台:WINDOWS 1.首先使用IDE写好需要调用的java代码,再添加"create or replace and compile java ...

  9. 谈论HashMap,HashSet,HashTableeasy被我们忽视

    在正常发育,HashMap,HashTable,HashSet 他们批准了经常使用的按键值地图数据结构.在这里,我主要写一些平时我们使用的这些数据结构easy忽略. HashMap HashMap的结 ...

  10. hdu 亲和串(kmp)

    Problem Description 人随着岁数的增长是越大越聪明还是越大越笨,这是一个值得全世界科学家思考的问题,同样的问题Eddy也一直在思考,因为他在很小的时候就知道亲和串如何判断了,但是发现 ...