在前面的大部分例子我们使用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. [WebGL入门]四,渲染准备

    注意:文章翻译http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:].另外.鄙人webgl研究还不够深入,一些专业词语,假设翻译有误,欢迎大家 ...

  2. 使用php+swoole对client数据实时更新(二) (转)

    上一篇提到了swoole的基本使用,现在通过几行基本的语句来实现比较复杂的逻辑操作: 先说一下业务场景.我们目前的大多数应用都是以服务端+接口+客户端的方式去协调工作的,这样的好处在于不论是处在何种终 ...

  3. schema for clojure

    Schema for Clojure Data Shape Declaration and Validation 1.何为schema schema是描写叙述数据形式的一种clojure数据结构,可用 ...

  4. php用魔术方法__call实现类函数重载

    因为php是弱类型语言,不喜欢c++通过改变函数返回相同的值键入的参数的数目和功能将过载!但在需求函数的实际发展可能过载.开发需求,我们能够通过魔术方法__call()来实现函数重载. class T ...

  5. Spring AOP在pointcut expression解析表达式 并匹配多个条件

    Pointcut 方法是那些需要运行"AOP",由"Pointcut Expression"为了描述叙事. Pointcut以下方法可以通过定义任&&a ...

  6. 《TCP/IP具体解释》读书笔记(18章)-TCP连接的建立与中止

    TCP是一个面向连接的协议.不管哪一方向还有一方发送数据之前.都必须在两方之间建立一条连接.这样的两端间连接的建立与无连接协议UDP不同.UDP向还有一端发送数据报时,无需不论什么预告的握手. 1.建 ...

  7. iOS6和iOS7适应代码(6) —— NSLocalizedString

    我们的应用程序都需要国际化,字符串的重要组成部分.一般来说.我们是通过一个string资源文件来达到这个目的,我们需要支持多国语言,有多少次把这个文档本地化.需要使用的代码NSLocalizedStr ...

  8. WinForm实现类似QQ停靠,显示隐藏过程添加特效效果

    原文:WinForm实现类似QQ停靠,显示隐藏过程添加特效效果 这可能是个老题长谈的问题了,只是在项目中会用到这个效果,所以今天做个记录.大家见了别喷我.在项目中的需求是这样的. 打开程序,在屏幕的右 ...

  9. 面向对象三大特征之多态——Java笔记(七)

    多态:     同一个实体同时具有多种形式     编译时的类型有声明该变量时使用的类型决定,运行时的类型有实际赋值给变量的对象决定     如果编译时类型和运行时类型不同,就出现多态 例: clas ...

  10. ural 1932 The Secret of Identifier 容斥

    主题链接:点击打开链接 stl+容斥 #include <cstdio> #include <cstring> #include <algorithm> #incl ...