默认情况下,<context:component-scan>查找使用构造型(stereotype)注解所标注的类,如@Component(组件),@Service(服务),@Controller(控制器),@Repository(数据仓库)

我们具体看下<context:component-scan>的一些属性,以下是一个比较具体的<context:component-scan>配置

<context:component-scan base-package="com.wjx.betalot" <!-- 扫描的基本包路径 -->
annotation-config="true" <!-- 是否激活属性注入注解 -->
name-generator="org.springframework.context.annotation.AnnotationBeanNameGenerator" <!-- Bean的ID策略生成器 -->
resource-pattern="**/*.class" <!-- 对资源进行筛选的正则表达式,这边是个大的范畴,具体细分在include-filter与exclude-filter中进行 -->
scope-resolver="org.springframework.context.annotation.AnnotationScopeMetadataResolver" <!-- scope解析器 ,与scoped-proxy只能同时配置一个 -->
scoped-proxy="no" <!-- scope代理,与scope-resolver只能同时配置一个 -->
use-default-filters="false" <!-- 是否使用默认的过滤器,默认值true -->
>
<!-- 注意:若使用include-filter去定制扫描内容,要在use-default-filters="false"的情况下,不然会“失效”,被默认的过滤机制所覆盖 -->
<!-- annotation是对注解进行扫描 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
<!-- assignable是对类或接口进行扫描 -->
<context:include-filter type="assignable" expression="com.wjx.betalot.performer.Performer"/>
<context:include-filter type="assignable" expression="com.wjx.betalot.performer.impl.Sonnet"/> <!-- 注意:在use-default-filters="false"的情况下,exclude-filter是针对include-filter里的内容进行排除 -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="assignable" expression="com.wjx.betalot.performer.impl.RainPoem"/>
<context:exclude-filter type="regex" expression=".service.*"/> </context:component-scan>

以上配置注释已经很详细了,当然因为这些注释,你若是想复制去验证,你得删掉注释。我们具体再说明一下这些注释:

back-package:标识了<context:component-scan>元素所扫描的包,可以使用一些通配符进行配置

annotation-config:<context:component-scan>元素也完成了<context:annotation-config>元素的工作,开关就是这个属性,false则关闭属性注入注解功能

name-generator:这个属性指定你的构造型注解,注册为Bean的ID生成策略,这个生成器基于接口BeanNameGenerator实现generateBeanName方法,你可以自己写个类去自定义策略。这边,我们可不显示配置,它是默认使用org.springframework.context.annotation.AnnotationBeanNameGenerator生成器,也就是类名首字符小写的策略,如Performer类,它注册的Bean的ID为performer.并且可以自定义ID,如@Component("Joy").这边简单贴出这个默认生成器的实现。

public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
if (definition instanceof AnnotatedBeanDefinition) {
String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
if (StringUtils.hasText(beanName)) {
// Explicit bean name found.
return beanName;
}
}
// Fallback: generate a unique default bean name.
return buildDefaultBeanName(definition, registry);
}

Spring除了实现了AnnotationBeanNameGenerator生成器外,还有个org.springframework.beans.factory.support.DefaultBeanNameGenerator生成器,它为了防止Bean的ID重复,它的生成策略是类路径+分隔符+序号

,如com.wjx.betalot.performer.impl.Sonnet注册为Bean的ID是com.wjx.betalot.performer.impl.Sonnet#0,这个生成器不支持自定义ID,否则抛出异常。同样贴出代码,有兴趣的可以去看下。

public static String generateBeanName(
BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean)
throws BeanDefinitionStoreException { String generatedBeanName = definition.getBeanClassName();
if (generatedBeanName == null) {
if (definition.getParentName() != null) {
generatedBeanName = definition.getParentName() + "$child";
}
else if (definition.getFactoryBeanName() != null) {
generatedBeanName = definition.getFactoryBeanName() + "$created";
}
}
if (!StringUtils.hasText(generatedBeanName)) {
throw new BeanDefinitionStoreException("Unnamed bean definition specifies neither " +
"'class' nor 'parent' nor 'factory-bean' - can't generate bean name");
} String id = generatedBeanName;
if (isInnerBean) {
// Inner bean: generate identity hashcode suffix.
id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(definition);
}
else {
// Top-level bean: use plain class name.
// Increase counter until the id is unique.
int counter = -1;
while (counter == -1 || registry.containsBeanDefinition(id)) {
counter++;
id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + counter;
}
}
return id;
}

resource-pattern:对资源进行筛选的正则表达式,这边是个大的范畴,具体细分在include-filter与exclude-filter中进行。

scoped-proxy: scope代理,有三个值选项,no(默认值),interfaces(接口代理),targetClass(类代理),那什么时候需要用到scope代理呢,举个例子,我们知道Bean的作用域scope有singleton,prototype,request,session,那有这么一种情况,当你把一个session或者request的Bean注入到singleton的Bean中时,因为singleton的Bean在容器启动时就会创建A,而session的Bean在用户访问时才会创建B,那么当A中要注入B时,有可能B还未创建,这个时候就会出问题,那么代理的时候来了,B如果是个接口,就用interfaces代理,是个类则用targetClass代理。这个例子出处:http://www.bubuko.com/infodetail-1434289.html。

scope-resolver:这个属性跟name-generator有点类似,它是基于接口ScopeMetadataResolver的,实现resolveScopeMetadata方法,目的是为了将@Scope(value="",proxyMode=ScopedProxyMode.NO,scopeName="")的配置解析成为一个ScopeMetadata对象,Spring这里也提供了两个实现,我们一起看下。首先是org.springframework.context.annotation.AnnotationScopeMetadataResolver中,

public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
ScopeMetadata metadata = new ScopeMetadata();
if (definition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(annDef.getMetadata(), this.scopeAnnotationType);
if (attributes != null) {
metadata.setScopeName(attributes.getAliasedString("value", this.scopeAnnotationType, definition.getSource()));
ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == null || proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = this.defaultProxyMode;
}
metadata.setScopedProxyMode(proxyMode);
}
}
return metadata;
}

对比一下org.springframework.context.annotation.Jsr330ScopeMetadataResolver中的实现:

public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
ScopeMetadata metadata = new ScopeMetadata();
metadata.setScopeName(BeanDefinition.SCOPE_PROTOTYPE);
if (definition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
Set<String> annTypes = annDef.getMetadata().getAnnotationTypes();
String found = null;
for (String annType : annTypes) {
Set<String> metaAnns = annDef.getMetadata().getMetaAnnotationTypes(annType);
if (metaAnns.contains("javax.inject.Scope")) {
if (found != null) {
throw new IllegalStateException("Found ambiguous scope annotations on bean class [" +
definition.getBeanClassName() + "]: " + found + ", " + annType);
}
found = annType;
String scopeName = resolveScopeName(annType);
if (scopeName == null) {
throw new IllegalStateException(
"Unsupported scope annotation - not mapped onto Spring scope name: " + annType);
}
metadata.setScopeName(scopeName);
}
}
}
return metadata;
}

ps:scope-resolver与scoped-proxy只能配置一个,配置了scope-resolver后你要使用代理,可以配置@Scope总的proxyMode属性项

use-default-filters:是否使用默认的扫描过滤。

<context:include-filter> :用来告知哪些类需要注册成Spring Bean,使用type和expression属性一起协作来定义组件扫描策略。type有以下5种

过滤器类型 描述
annotation 过滤器扫描使用注解所标注的那些类,通过expression属性指定要扫描的注释
assignable 过滤器扫描派生于expression属性所指定类型的那些类
aspectj 过滤器扫描与expression属性所指定的AspectJ表达式所匹配的那些类
custom 使用自定义的org.springframework.core.type.TypeFliter实现类,该类由expression属性指定
regex 过滤器扫描类的名称与expression属性所指定正则表示式所匹配的那些类

要注意的是:若使用include-filter去定制扫描内容,要在use-default-filters="false"的情况下,不然会“失效”,被默认的过滤机制所覆盖

<context:exclude-filter>:与<context:include-filter> 相反,用来告知哪些类不需要注册成Spring Bean,同样注意的是:在use-default-filters="false"的情况下,exclude-filter是针对include-filter里的内容进行排除。

<context:component-scan>详解的更多相关文章

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">的含义

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/x ...

  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    关于网页中第一行<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www ...

  3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">详解

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"的作用

    为页面添加正确的DOCTYPE 很多设计师和开发者都不知道什么是DOCTYPE,DOCTYPE有什么用.DOCTYPE是document type的简写.主要用来说明你用的XHTML或者HTML是什么 ...

  5. Vue2.0史上最全入坑教程(中)—— 脚手架代码详解

    书接上文我们说道,如何利用脚手架(vue-cli)构建一个vue项目,本回书我们一起来学习分析下代码. 回顾下创建后的项目目录:   说明:在*.vue文件,template标签里写html代码,且t ...

  6. Windows7 QT5.6.0(64位)使用mysql(64位)环境搭建详解

    1 说明 使用环境为:Windows7 VS2015 QT5.6.0(64位),MYSQL 5.7.13(64位). 网上各种错误.模糊.抽象的资料,配置环境花了半天,痛定思痛,总结出来,方便后来人. ...

  7. IDEA里运行代码时出现Error:scalac: error while loading JUnit4, Scala signature JUnit4 has wrong version expected: 5.0 found: 4.1 in JUnit4.class错误的解决办法(图文详解)

    不多说,直接上干货!  问题详情 当出现这类错误时是由于版本不匹配造成的 Information:// : - Compilation completed with errors and warnin ...

  8. 安装mysql8.0.11及修改root密码、连接navicat for mysql的思路详解

    1.1. 下载: 官网下载zip包,我下载的是64位的: 下载地址:https://dev.mysql.com/downloads/mysql/ 下载zip的包: 下载后解压:(解压在哪个盘都可以的) ...

  9. XHTML 1.0 的三种 XML 文档类型 DOCTYPE

    XHTML 1.0 的三种 XML 文档类型 XHTML 1.0 规定了三种 XML 文档类型 XHTML 1.0 Strict <!DOCTYPE html PUBLIC "-//W ...

  10. DOCTYPE html PUBLIC 指定了 HTML 文档遵循的文档类型定义

    DOCTYPE html PUBLIC 指定了 HTML 文档遵循的文档类型定义 今天看到一篇CSS应用的一个友好搜索,我按网页上的代码复制.粘贴后预览时总达不到效果,而直接拷贝他的实例却能达到效果, ...

随机推荐

  1. 将ADS1.2的工程迁移到KEIL上-基于2440

    裸机程序应该是一个很好的选择 1. 不拷贝启动代码,因为我们用自己的启动代码 2.       建立工程目录分级,建立完成后如下所示 拷贝相应代码到对应目录中 Option中拷贝 Core中拷贝 建立 ...

  2. UVA 11542 Square ——线性基

    [题目分析] 每个数没有超过500的因子.很容易想到把每一个数表示成一个二进制的数. (0代表该质数的次数为偶数,1代表是奇数) 然后问题转化成了选取一些二进制数,使他们的异或和为0. 高斯消元,2^ ...

  3. iOS UIActivityIndicatorView 的使用

    UIActivityIndicatorView 非常简单 ,就是一个转圈圈的控件:http://blog.csdn.net/zhaopenghhhhhh/article/details/1209265 ...

  4. IOS之富文本编辑 分类: ios技术 2015-03-06 22:51 89人阅读 评论(0) 收藏

    之前做项目时遇到一个问题:          使用UITextView显示一段电影的简介,由于字数比较多,所以字体设置的很小,行间距和段间距也很小,一大段文字挤在一起看起来很别扭,想要把行间距调大,结 ...

  5. Maven项目中pom文件分析

    pom英文全称: project object model 1.概述 pom.xml文件描述了maven项目的基本信息,比如groupId,artifactId,version等.也可以对maven项 ...

  6. mongodb学习(二)分级查询数组中的值

    (PS: 标题有点不妥当...) 大概是这样...数据结构如下: 需要模糊查询title的值... mongodb中操作语句: 主要是注意这里urlElements不需要加[0]...我开始的时候写成 ...

  7. 使用YUIDoc生成JS文档

    其实YUIDoc主页已经写的比较清晰了,但有一些概念和细节再点出一些注意的地方. 目前最新的YUIDoc使用nodejs进行开发安装和使用都非常的方便. 我们只需要将我们的代码加上必要的注释,便可以很 ...

  8. netstat 查看连接数

    1.查看Web服务器(Nginx Apache)的并发请求数及其TCP连接状态: netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print ...

  9. Mac 安装Eclipse

    1.下载 1.1.网址 http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/mar ...

  10. Zepto swipe 无效(坑)

    Zepto 滑动插件 bug Zepto 的 'swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown' 触摸事件在安卓4.4系统中除chro ...