<context:component-scan base-package="com.zhuguang.jack" <!-- 扫描的基本包路径 -->
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"/>
<context:exclude-filter type="regex" expression=".controller.*"/>
<!-- 注意:在use-default-filters="false"的情况下,exclude-filter是针对include-filter里的内容进行排除,
有Controller注解的排除,
-->
<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>
public BeanDefinition parse(Element element, ParserContext parserContext) {
String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); //[com.zhuguang.jack] ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); //扫描器
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null;
}
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
XmlReaderContext readerContext = parserContext.getReaderContext(); //XmlReaderContext@704deff2
boolean useDefaultFilters = true;
if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)); //默认过滤器
}
ClassPathBeanDefinitionScanner scanner = createScanner(readerContext, useDefaultFilters); //扫描器
return scanner;
}
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
for (String basePackage : basePackages) {
Set<BeanDefinition> candidates = findCandidateComponents(basePackage); // [[AnnotationServiceImpl];], [CommonController]; ]],
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); //往bean定义里面设置属性,setLazyInit,setAutowireMode,setDependencyCheck,setInitMethodName,setEnforceInitMethod,setDestroyMethodName,setEnforceDestroyMethod都设置默认值,
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); //往bean定义里面设置属性,是否有Lazy,Primary,DependsOn,Role,Description注解,如果有就设置到bean定义中去。
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); //把BeanDefinition 变成BeanDefinitionHolder,
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); //
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry); //注册到spring容器中,
}
}
}
return beanDefinitions;
}
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
try {
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + "/" + this.resourcePattern; //classpath*:com/zhuguang/jack/**/*.class找到所有的。class文件,
Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath); //[file [E:AnnotationServiceImpl.class], file [E:CommonController.class], file [E:CommonMapper.class], file [E:ConsultConfigArea.class], file [E:ConsultContent.class], file [E:MyService.class], file [E:Test2.class], file [E:User.class]]
for (Resource resource : resources) {
if (isCandidateComponent(metadataReader) && resource.isReadable()) { //没有条件注解,就进来,没有注解的不进来。有@Component注解的才进来,
try {
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource); //AnnotationMetadata里面封装了这个类的一些基本信息,类里面有哪些方法,方法上面有哪些注解,类上面有哪些注解,
if (isCandidateComponent(metadataReader)) {//!(this.isInterface || this.isAbstract) && (this.enclosingClassName == null || this.independentInnerClass); 不是接口不是抽象类就进来,CommonMapper是一个接口不进来,
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
candidates.add(sbd);
}
else {
}
}
}
}
}
}
return candidates;
}
public MetadataReader getMetadataReader(Resource resource) throws IOException {
return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader());
}
SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException {
InputStream is = new BufferedInputStream(resource.getInputStream());//文件流,
ClassReader classReader;
classReader = new ClassReader(is); AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader);
classReader.accept(visitor, ClassReader.SKIP_DEBUG); this.annotationMetadata = visitor;
this.classMetadata = visitor;
this.resource = resource;
}
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {  //metadataReader是类的元数据信息,
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, this.metadataReaderFactory)) {
return false;
}
}
for (TypeFilter tf : this.includeFilters) {//interface org.springframework.stereotype.Component,interface javax.inject.Named。有@Component注解的才进来,
if (tf.match(metadataReader, this.metadataReaderFactory)) {
return isConditionMatch(metadataReader);
}
}
return false;
}
public Resource[] getResources(String locationPattern) throws IOException {
if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
return findPathMatchingResources(locationPattern);
}
}
}
protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
String rootDirPath = determineRootDir(locationPattern); //classpath*:com/zhuguang/jack/
String subPattern = locationPattern.substring(rootDirPath.length()); //**/*.class
Resource[] rootDirResources = getResources(rootDirPath); //返回[URL [file:/E:/Code/AAAAA/AAAAA/2019326/2/spring-source-web-master-aop/target/classes/com/zhuguang/jack/]]
Set<Resource> result = new LinkedHashSet<Resource>();
for (Resource rootDirResource : rootDirResources) {
rootDirResource = resolveRootDirResource(rootDirResource); //返回[URL [file:/E:/Code/AAAAA/AAAAA/2019326/2/spring-source-web-master-aop/target/classes/com/zhuguang/jack/]]
if (isJarResource(rootDirResource)) {
result.addAll(doFindPathMatchingJarResources(rootDirResource, subPattern));
}
else if (rootDirResource.getURL().getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirResource, subPattern, getPathMatcher()));
}
else {
result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
}
}
return result.toArray(new Resource[result.size()]); //[file [E:AnnotationServiceImpl.class], file [E:CommonController.class], file [E:CommonMapper.class], file [E:ConsultConfigArea.class], file [E:ConsultContent.class], file [E:MyService.class], file [E:Test2.class], file [E:User.class]]
}
public Resource[] getResources(String locationPattern) throws IOException {
else {
return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
}
}
} protected Resource[] findAllClassPathResources(String location) throws IOException {
Enumeration<URL> resourceUrls = getClassLoader().getResources(path); //AppClassLoader,返回[sun.misc.CompoundEnumeration@b83a9be, java.net.URLClassLoader$3@2609b277]
Set<Resource> result = new LinkedHashSet<Resource>();
while (resourceUrls.hasMoreElements()) {
URL url = resourceUrls.nextElement();
result.add(convertClassLoaderURL(url));
}
return result.toArray(new Resource[result.size()]); //返回[URL [file:/E:/Code/AAAAA/AAAAA/2019326/2/spring-source-web-master-aop/target/classes/com/zhuguang/jack/]]
}
public Enumeration<URL> getResources(String name) throws IOException {
@SuppressWarnings("unchecked")
Enumeration<URL>[] tmp = (Enumeration<URL>[]) new Enumeration<?>[];
if (parent != null) {
tmp[] = parent.getResources(name); //ExtClassLoader
} else {
tmp[] = getBootstrapResources(name);
}
tmp[] = findResources(name); return new CompoundEnumeration<>(tmp);
}
private static Enumeration<URL> getBootstrapResources(String name)   {
final Enumeration<Resource> e = getBootstrapClassPath().getResources(name); //sun.misc.URLClassPath@28d18df5
return new Enumeration<URL> () {
public URL nextElement() {
return e.nextElement().getURL();
}
public boolean hasMoreElements() {
return e.hasMoreElements();
}
}
}

spring context:component-scan的更多相关文章

  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注解Component原理源码解析

    在实际开发中,我们经常使用Spring的@Component.@Service.@Repository以及 @Controller等注解来实现bean托管给Spring容器管理.Spring是怎么样实 ...

  3. Spring context:component-scan中使用context:include-filter和context:exclude-filter

    Spring context:component-scan中使用context:include-filter和context:exclude-filter XML: <?xml version= ...

  4. Spring context:component-scan代替context:annotation-config

    Spring context:component-scan代替context:annotation-config XML: <?xml version="1.0" encod ...

  5. Spring <context:annotation-config> 与<context-component-scan> 的作用

    <context:annotation-config> 与<context-component-scan> 的作用 <context:annotation-config& ...

  6. Spring <context:component-scan>标签属性 use-default-filters 以及子标签 include-filter使用说明

    Spring <context:component-scan>标签作用有很多,最基本就是 开启包扫描,可以使用@Component.@Service.@Component等注解: 今天要作 ...

  7. Spring 注解@Component,@Service,@Controller,@Repository

    Spring 注解@Component,@Service,@Controller,@RepositorySpring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释, ...

  8. [转载]vs2012中使用Spring.NET报错:Spring.Context.Support.ContextRegistry 的类型初始值设定项引发异常

    学习使用Spring.NET中的时候,写了一个Demo,在运行时报了一个错误:Spring.Context.Support.ContextRegistry 的类型初始值设定项引发异常. 重新整理思绪, ...

  9. 使用web.xml方式加载Spring时,获取Spring context的两种方式

    使用web.xml方式加载Spring时,获取Spring context的两种方式: 1.servlet方式加载时: [web.xml] <servlet> <servlet-na ...

  10. 【报错】spring整合activeMQ,pom.xml文件缺架包,启动报错:Caused by: java.lang.ClassNotFoundException: org.apache.xbean.spring.context.v2.XBeanNamespaceHandler

    spring版本:4.3.13 ActiveMq版本:5.15 ======================================================== spring整合act ...

随机推荐

  1. 配置vtk(Win8.1 + VS2012+VTK-5.10.1)

    1.下载相关软件 vtk-5.10.1.zip和vtkdata-5.10.1.zip http://www.vtk.org/files/release/5.10/vtk-5.10.1.zip http ...

  2. Hbase内存磁盘大致关系

    转自: https://blog.csdn.net/wuwenxiang91322/article/details/51595771 Hbase内存磁盘关系磁盘数 diskNum磁盘容量 diskCa ...

  3. php使用inotify扩展监控文件或目录,如果发生改变,就执行指定命令

    通过inotify扩展监控文件或目录的变化,如果发生变化,就执行命令. 可以应用于 swoole 中,如果文件发生变化,就执行 kill -USR1 进程PID 来实现热更新. <?php cl ...

  4. JXL工具包对Excle文件操作

    1.简介: XL - JXL(Java Excel API)是一个用来动态读写 Excel 文件的开源框架,利用它可以 在任何支持 Java 的操作系统上动态读写 Excel 文件. 2.开发步骤 1 ...

  5. fastjson对于yyyy-MM-dd HH:mm格式的反序列化问题

    原创GrayHJX 发布于2017-03-14 22:56:33 阅读数 6851  收藏 展开 问题:最近在工作中遇到这么一个问题:有个实体类,它有个date类型的属性,当在这个属性加上fastjs ...

  6. C# ICloneable,shallow clone,deep clone.

    [Serializable] public class Person:ICloneable { public string Name { get; set; } public int Id { get ...

  7. Vue笔记--通过自定义指令实现按钮操作权限

    经常做中后台系统,此类系统的权限是比较重要,拿自己做过的一些项目做个笔记. Vue实现的中后台管理系统.按钮操作权限的空置一般都是通过自定义指令Vue.directive. <el-button ...

  8. Android开发利器之pidcat

    介绍pidcat: pidcat 是Android届JakeWharton大神开发的一款命令行工具,堪称Android开发利器,它能方便Android程序猿捕获日志,过滤日志,定位程序问题,超级好用. ...

  9. 【团队项目3】需求改进&系统设计

    一.需求 & 原型改进 1.针对课堂讨论环节老师和其他组的问题及建议,对修改选题及需求进行修改 根据用户反馈,我们针对如下问题做了修改: 问题1:如何保证机构是否是官方的?平台是否有监管? 修 ...

  10. 大数据分析的下一代架构--IOTA架构设计实践[下]

    大数据分析的下一代架构--IOTA架构设计实践[下] 原创置顶 代立冬 发布于2018-12-31 20:59:53 阅读数 2151  收藏 展开 IOTA架构提出背景 大数据3.0时代以前,Lam ...