<context:component-scan>详解 转发 https://www.cnblogs.com/fightingcoding/p/component-scan.html
<context:component-scan>详解
默认情况下,<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>详解 转发 https://www.cnblogs.com/fightingcoding/p/component-scan.html的更多相关文章
- MemCache在.NET中使用Memcached.ClientLibrary详解 转发 https://www.cnblogs.com/li150dan/p/9529112.html
本文说明:memcached分布式缓存的负载均衡配置比例,数据压缩,socket的详细配置等,以及在.net中的常用方法 首先下载客户端的3个dll,ICSharpCode.SharpZipLib.d ...
- [转帖]Nginx安装及配置详解 From https://www.cnblogs.com/zhouxinfei/p/7862285.html
Nginx安装及配置详解 nginx概述 nginx是一款自由的.开源的.高性能的HTTP服务器和反向代理服务器:同时也是一个IMAP.POP3.SMTP代理服务器:nginx可以作为一个HTTP ...
- Autofac框架详解 转载https://www.cnblogs.com/lenmom/p/9081658.html
一.组件 创建出来的对象需要从组件中来获取,组件的创建有如下4种(延续第一篇的Demo,仅仅变动所贴出的代码)方式: 1.类型创建RegisterType AutoFac能够通过反射检查一个类型,选择 ...
- context.Session[“xxx”]详解
1.在aspx和aspx.cs中,都是以Session[“xxx”]=”aaa”和aaa=Session[“xxx”].ToString()进行读写.而在ashx中,Session都要使用contex ...
- 【知识详解】Https详解
Https详解 1.什么是Https Http + SSL = Https 一句话说:Https是身披SSL的Http,当使用了SSL后,Http先和SSL通信,再由SSL和TCP通信, 2.为什么需 ...
- hashcode详解--转发
序言 写这篇文章是因为在看hashMap源码时遇到有什么hashcode值,然后就去查,脑袋里面是有映像的,不就是在Object中有equals和hashcode方法嘛,这在学java基础的时候就遇到 ...
- [转]Oracle 11g R2 RAC高可用连接特性 – SCAN详解
原文地址:http://czmmiao.iteye.com/blog/2124373 昨天帮朋友解决11g RAC SCAN问题,当时为这朋友简单解答了一些SCAN特性相关的问题,但我知道这仅仅是 ...
- Cordova入门系列(三)Cordova插件调用 转发 https://www.cnblogs.com/lishuxue/p/6018416.html
Cordova入门系列(三)Cordova插件调用 版权声明:本文为博主原创文章,转载请注明出处 上一章我们介绍了cordova android项目是如何运行的,这一章我们介绍cordova的核心 ...
- .Net使用RabbitMQ详解 转载http://www.cnblogs.com/knowledgesea/p/5296008.html
.Net使用RabbitMQ详解 序言 这里原来有一句话,触犯啦天条,被阉割!!!! 首先不去讨论我的日志组件怎么样.因为有些日志需要走网络,有的又不需要走网路,也是有性能与业务场景的多般变化在其 ...
随机推荐
- nodejs的优点
nodejs主要用于搭建高性能的web服务器,优点如下: 可以解决高并发,它是单线程,当访问量很多时,将访问者分配到不同的内存中,不同的内存区做不同的事,以快速解决这个线程.就像医院的分科室看病人.效 ...
- bootstrap模态框的调用
1.<a href="JavaScript:void(0);" class="bs-tooltip remark-item" rel="{$bi ...
- 第四章 代词(Les pronoms )
★人称代词 .主语人称代词 第一人称和第二人称属纯人称代词,只能代人不能代物;第三人称可代人,亦可代物.如: La Terre est ronde. Elle tourne autour du Sol ...
- 【Unity】2.0 第2章 Unity编辑器和基本操作
分类:Unity.C#.VS2015 创建日期:2016-03-26 本章要点: 1.掌握Unity 5.3.4编辑器视图和菜单项及其含义,这是入门的最基础部分,必须掌握. 2.了解最基本的操作,先学 ...
- file.write(str),file.writelines(sequence)
file.write(str)的参数是一个字符串,就是你要写入文件的内容.file.writelines(sequence)的参数是序列,比如列表,它会迭代帮你写入文件.
- scrapy windows 安装
windows 7 系统下参照官网安装总是会提示出错,现在整理一下安装的流程 1.安装 python 2.7,添加环境变量 C:\Python27\;C:\Python27\Scripts\; 在 C ...
- 【翻译】JavaScript框架的最终指南
翻译原文链接 我的翻译小站 紧跟JavaScript框架的脚步是一个挑战.现在有太多的框架,几乎一个月就会出来一个新的.那么如何知道到底哪一个比较合适你的项目呢?它们分别有什么优点和缺点呢?你要如何开 ...
- EBS获取附件URL
http://wenku.baidu.com/link?url=MnYX269RBqW9ZRh-4famwduhYq9As0-vsIyVPA7aqv64cdxxjZEOaEE1_KZ9SGjY9qCx ...
- C#使用cplex求解简单线性规划问题(Cplex系列-教程二)
若还未在项目中添加cplex的引用,可以参阅上一篇文章.本文主要介绍利用C#求解线性规划的步骤,对线性规划模型进行数据填充的两种方法,以及一些cplex函数的功能和用法.包括以下几个步骤: 描述 先花 ...
- C#: 获取当前路径不要用Environment.CurrentDirectory
网上大把文章写到C#获取当前路径的方法如下: // 获取程序的基目录. System.AppDomain.CurrentDomain.BaseDirectory // 获取模块的完整路径. Syste ...