首页 > 作文

Spring ComponentScan的扫描过程解析

更新时间:2023-04-06 03:56:44 阅读: 评论:0

xml中的扫描过程

<?xml version="1.0" encoding="utf-8" ?><beans xmlns="/d/file/titlepic/"   xmlns:xsi="/d/file/titlepic/xmlschema-instance"   xmlns:context="/d/file/titlepic/"   xsi:schemalocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context /d/file/titlepic/spring-context.xsd"   default-lazy-init="fal"><context:component-scan ba-package="com.morris.spring.demo.rvice"/></beans>

xml中使用自定义标签context实现,最终会调用到componentscanbeandefinitionparr.par()方法进行解析。

componentscanbeandefinitionparr.par()

// org.springframework.context.annotation.componentscanbeandefinitionparr#parpublic beandefinition par(element element, parrcontext parrcontext) {// 获得ba-package指定的包名string bapackage = element.getattribute(ba_package_attribute);bapackage = parrcontext.getreadercontext().getenvironment().resolveplaceholders(bapackage);// ba-package中可能有多个,用逗号分隔,转换为数组string[] bapackages = stringutils.tokenizetostringarray(bapackage,configurableapplicationcontext.config_location_delimiters);// actually scan for bean definitions and register them.// 创建扫描器classpathbeandefinitionscanner scanner = configurescanner(parrcontext, element);// 开始扫描t<beandefinitionholder> beandefinitions = scanner.doscan(bapackages);// 注册了一些组件// configurationclasspostprocessor// autowiredannotationbeanpostprocessor// commonannotationbeanpostprocessor// eventlistenermethodprocessor// defaulteventlistenerfactoryregistercomponents(parrcontext.getreadercontext(), beandefinitions, element);return null;}

component最新奶粉热卖排行榜scanbeandefinitionparr#configurescanner

创建扫描器classpathbeandefinitionscanner

protected classpathbeandefinitionscanner configurescanner(parrcontext parrcontext, element element) {    boolean udefaultfilters = true;    if (element.hasattribute(u_default_filters_attribute)) {        udefaultfilters = boolean.parboolean(element.getattribute(u_default_filters_attribute));    }    // delegate bean definition registration to scanner class.    // classpathbeandefinitionscanner构造方法中添加了默认的includefilters为@component    classpathbeandefinitionscanner scanner = createscanner(parrcontext.getreadercontext(), udefaultfilters);    scanner.tbeandefinitiondefaults(parrcontext.getdelegate().getbeandefinitiondefaults());    scanner.tautowirecandidatepatterns(parrcontext.getdelegate().getautowirecandidatepatterns());    if (element.hasattribute(resource_pattern_attribute)) {        scanner.tresourcepattern(element.getattribute(resource_pattern_attribute));    }    try {        parbeannamegenerator(element, scanner);    }    catch (exception ex) {        parrcontext.getreadercontext().error(ex.getmessage(), parrcontext.extractsource(element), ex.getcau());    }    try {        parscope(element, scanner);    }    catch (exception ex) {        parrcontext.getreadercontext().error(ex.getmessage(), parrcontext.extractsource(element), ex.getcau());    }    partypefilters(element, scanner, parrcontext);    return scanner;}

怎么知道扫描哪些注解呢?

classpathbeandefinitionscanner构造方法中会注入默认的filter。

protected void registerdefaultfilters() {    // 只扫描@component注解了的类,而@vice、@configuration、@controller等注解都被@component修饰    this.includefilters.add(new annotationtypefilter(component.class));    classloader cl = classpathscanningcandidatecomponentprovider.class.getclassloader();    try {        this.includefilters.add(new annotationtypefilter(                ((class<? extends annotation>) classutils.forname("javax.annotation.managedbean", cl)), fal));        logger.trace("jsr-250 'javax.annotation.managedbean' found and supported for component scanning");    }    catch (classnotfoundexception ex) {        // jsr-250 1.1 api (as included in java ee 6) not available - simply skip.    }    try {        this.includefilters.add(new annotationtypefilter(                ((class<? extends annotation>) classutils.forname("javax.inject.named", cl)), fal));        logger.trace("jsr-330 'javax.inject.named' annotation found and supported for component scanning");    }    catch (classnotfoundexception ex) {        // jsr-330 api not available - simply skip.    }}

在源码中只会扫描@component注解,而@vice、@configuration、@controller等注解都被@component修饰,最终都会被扫描到。

classpathbeandefinitionscanner#doscan

开始扫描:

// org.springframework.context.annotation.classpathbeandefinitionscanner#doscanprotected t<beandefinitionholder> doscan(string... bapackages) {asrt.notempty(bapackages, "at least one ba package must be specified");t<beandefinitionholder> beandefinitions = new linkedhasht<>();for (string bapackage : bapackages) {// 查找bapackage下所有被@component注解修饰了的类t<beandefinition> candidates = findcandidatecomponents(bapackage);for (beandefinition candidate : candidates) {// 上面findcandidatecomponents只是为bd设置了几个属性,bd的其他属性并没有初始化,所以需要遍历一次初始化属性并注册到registryscopemetadata scopemetadata = this.scopemetadataresolver.resolvescopemetadata(candidate);candidate.tscope(scopemetadata.getscopename());string beanname = this.beannamegenerator.generatebeanname(candidate, this.registry);if (candidate instanceof abstractbeandefinition) {postprocessbeandefinition((abstractbeandefinition) candidate, beanname);}if (candidate instanceof ann历史必修二复习提纲otatedbeandefinition) {annotationconfigutils.processcommondefinitionannotations((annotatedbeandefinition) candidate);}if (checkcandidate(beanname, candidate)) {beandefinitionholder definitionholder = new beandefinitionholder(candidate, beanname);definitionholder =annotationconfigutils.applyscopedproxymode(scopemetadata, definitionholder, this.registry);beandefinitions.add(definitionholder);// 注册到registryregisterbeandefinition(definitionholder, this.registry);}}}return beandefinitions;}

classpathscanningcandidatecomponentprovider#scancandidatecomponents

查找bapackage下所有被@component注解修饰了的类:

// org.springframework.context.annotation.classpathscanningcandidatecomponentprovider#scancandidatecomponentsprivate t<beandefinition> scancandidatecomponents(string bapackage) {t<beandefinition> candidates = new linkedhasht<>();try {// bapackage=com.morris.spring..rvice// packagearchpath=classpath*:com/morris/spring/rvice/**/*.classstring packagearchpath = resourcepatternresolver.classpath_all_url_prefix +resolvebapackage(bapackage) + '/' + this.resourcepattern;// 获取bapackage下所有的class文件resource[] resources = getresourcepatternresolver().getresources(packagearchpath);boolean traceenabled = logger.istraceenabled();boolean debugenabled = logger.isdebugenabled();for (resource resource : resources) {if (traceenabled) {logger.trace("scanning " + resource);}if (resource.isreadable()) {try {// 使用asm将class文件的内容封装为metadatareader对象// 注意这里用的不是反射,反射会加载类,占用堆空间metadatareader metadatareader = getmetadatareaderfactory().getmetadatareader(resource);// 判断类是否包含@component注解if (iscandidatecomponent(metadatareader)) {// 封装为bdscannedgenericbeandefinition sbd = new scannedgenericbeandefinition(metadatareader);sbd.tsource(resource);if (iscandidatecomponent(sbd)) {if (debugenabled) {logger.debug("identified candidate component class: " + resource);}candidates.add(sbd);}... ...return candidates;}

registerannotationconfigprocessors

注册了多种重要的组件:

public static t<beandefinitionholder> registerannotationconfigprocessors(beandefinitionregistry registry, @nullable object source) {defaultlistablebeanfactory beanfactory = unwrapdefaultlistablebeanfactory(registry);if (beanfactory != null) {if (!(beanfactory.getdependencycomparator() instanceof annotationawareordercomparator)) {beanfactory.tdependencycomparator(annotationawareordercomparator.instance);}if (!(beanfactory.getautowirecandidateresolver() instanceof contextannotationautowirecandidateresolver)) {beanfactory.tautowirecandidateresolver(new contextannotationautowirecandidateresolver());}}t<beandefinitionholder> beandefs = new linkedhasht<>(8);// beanfactorypostprocessorif (!registry.containsbeandefinition(configuration_annotation_processor_bean_name)) {rootbeandefinition def = new rootbeandefinition(configurationclasspostprocessor.class);def.tsource(source);beandefs.add(registerpostprocessor(registry, def, configuration_annotation_processor_bean_name));}// beanpostprocessorif (!registry.containsbeandefinition(autowired_annotation_processor_bean_name)) {rootbeandefinition def = new rootbeandefinition(autowiredannotationbeanpostprocessor.class);def.tsource(source);beandefs.add(registerpostprocessor(registry, def, autowired_annotation_processor_bean_name));}// check for jsr-250 support, and if prent add the commonannotationbeanpostprocessor.if (jsr250prent && !registry.containsbeandefinition(common_annotation_processor_bean_name)) {rootbeandefinition def = new rootbeandefinition(commonannotationbeanpostprocessor.class);def.tsource(source);beandefs.add(registerpostprocessor(registry, def, common_annotation_processor_bean_name));}// check for jpa support, and if prent add the persistenceannotationbeanpostprocessor.if (jpaprent && !registry.containsbeandefinition(persistence_annotation_processor_bean_name)) {rootbeandefinition def = new rootbeandefinition();try {def.tbeanclass(classutils.forname(persistence_annotation_processor_class_name,annotationconfigutils.class.getclassloader()));}catch (classnotfoundexception ex) {throw new illegalstateexception("cannot load optional framework class: " + persistence_annotation_processor_class_name, ex);}def.tsource(source);beandefs.add(registerpostprocessor(registry, def, persistence_annotation_processor_bean_name));}// beanfactorypos经纬的意思tprocessorif (!registry.containsb心理学家的面相术eandefinition(event_listener_processor_bean_name)) {rootbeandefinition def = new rootbeandefinition(eventlistenermethodprocessor.class);def.tsource(source);beandefs.add(registerpostprocessor(registry, def, event_listener_processor_bean_name));}if (!registry.containsbeandefinition(event_listener_factory_bean_name)) {rootbeandefinition def = new rootbeandefinition(defaulteventlistenerfactory.class);def.tsource(source);beandefs.add(registerpostprocessor(registry, def, event_listener_factory_bean_name));}return beandefs;}

扫描的最终结果就是将类上面有@component注解的类构建为一个beandefinition中,spring容器中有两个集合来存放这些beandefinition:

beandefinitionnames:list<string>,存放所有的beandefinition对应的namebeandefinitionmap:map<string, beandefinition>,存放所有的beandefinition

注解的扫描过程

注解扫描的使用:

package com.morris.spring.demo.annotation;import com.morris.spring.demo.rvice.cityrvice;import org.springframework.context.annotation.annotationconfigapplicationcontext;import org.springframework.context.annotation.componentscan;@componentscan("com.morris.spring.rvice")public class componentscandemo {public static void main(string[] args) {annotationconfigapplicationcontext applicationcontext = new annotationconfigapplicationcontext(componentscandemo.class);cityrvice cityrvice = applicationcontext.getbean(cityrvice.class);cityrvice.city();}}

使用@componentscan注解指定包的扫描,扫描过程将由configurationclasspostprocessor#postprocessbeandefinitionregistry完成。

configurationclasspostprocessor#postprocessbeandefinitionregistry

public void postprocessbeandefinitionregistry(beandefinitionregistry registry) {int registryid = system.identityhashcode(registry);if (this.registriespostprocesd.contains(registryid)) {throw new illegalstateexception("postprocessbeandefinitionregistry already called on this post-processor against " + registry);}if (this.factoriespostprocesd.contains(registryid)) {throw new illegalstateexception("postprocessbeanfactory already called on this post-processor against " + registry);}this.registriespostprocesd.add(registryid);// 重支部工作计划点processconfigbeandefinitions(registry);}

configurationclasspostprocessor#processconfigbeandefinitions

public void processconfigbeandefinitions(beandefinitionregistry registry) {list<beandefinitionholder> configcandidates = new arraylist<>();string[] candidatenames = registry.getbeandefinitionnames();// 先收集有@configuration、@component、@componentscan、@import、@importresource、@bean的bdfor (string beanname : candidatenames) {beandefinition beandef = registry.getbeandefinition(beanname);if (beandef.getattribute(configurationclassutils.configuration_class_attribute) != null) {if (logger.isdebugenabled()) {logger.debug("bean definition has already been procesd as a configuration class: " + beandef);}}el if (configurationclassutils.checkconfigurationclasscandidate(beandef, this.metadatareaderfactory)) {// 进来需要@component、@componentscan、@import、@importresource、@beanconfigcandidates.add(new beandefinitionholder(beandef, beanname));}}    ... ...// par each @configuration classconfigurationclassparr parr = new configurationclassparr(this.metadatareaderfactory, this.problemreporter, this.environment,this.resourceloader, this.componentscanbeannamegenerator, registry);t<beandefinitionholder> candidates = new linkedhasht<>(configcandidates);t<configurationclass> alreadypard = new hasht<>(configcandidates.size());do {// 开始解析parr.par(candidates);parr.validate();

configurationclassparr#doprocessconfigurationclass

protected final sourceclass doprocessconfigurationclass(configurationclass configclass, sourceclass sourceclass, predicate<string> filter)throws ioexception {... ...// process any @componentscan annotations// 处理@componentscan注解,扫描包下带有@component的注解,与xml中自定义标签context:component-scan的扫描流程一致t<annotationattributes> componentscans = annotationconfigutils.attributesforrepeatable(sourceclass.getmetadata(), componentscans.class, componentscan.class);if (!componentscans.impty() &&!this.conditionevaluator.shouldskip(sourceclass.getmetadata(), configurationpha.register_bean)) {for (annotationattributes componentscan : componentscans) {// the config class is annotated with @componentscan -> perform the scan immediatelyt<beandefinitionholder> scannedbeandefinitions =this.componentscanparr.par(componentscan, sourceclass.getmetadata().getclassname());// check the t of scanned definitions for any further config class and par recursively if neededfor (beandefinitionholder holder : scannedbeandefinitions) {beandefinition bdcand = holder.getbeandefinition().getoriginatingbeandefinition();if (bdcand == null) {bdcand = holder.getbeandefinition();}// checkconfigurationclasscandidate这个里面会特殊处理@configutation为fullif (configurationclassutils.checkconfigurationclasscandidate(bdcand, this.metadatareaderfactory)) {par(bdcand.getbeanclassname(), holder.getbeanname());}}}}... ...return null;}

componentscanannotationparr#par

public t<beandefinitionholder> par(annotationattributes componentscan, final string declaringclass) {// 解析@componentscan注解,构建classpathbeandefinitionscanner// 构建方法中会添加默认的includefilters为@componentclasspathbeandefinitionscanner scanner = new classpathbeandefinitionscanner(this.registry,componentscan.getboolean("udefaultfilters"), this.environment, this.resourceloader);class<? extends beannamegenerator> generatorclass = componentscan.getclass("namegenerator");boolean uinheritedgenerator = (beannamegenerator.class == generatorclass);scanner.tbeannamegenerator(uinheritedgenerator ? this.beannamegenerator :beanutils.instantiateclass(generatorclass));scopedproxymode scopedproxymode = componentscan.getenum("scopedproxy");if (scopedproxymode != scopedproxymode.default) {scanner.tscopedproxymode(scopedproxymode);}el {class<? extends scopemetadataresolver> resolverclass = componentscan.getclass("scoperesolver");scanner.tscopemetadataresolver(beanutils.instantiateclass(resolverclass));}scanner.tresourcepattern(componentscan.getstring("resourcepattern"));for (annotationattributes filter : componentscan.getannotationarray("includefilters")) {for (typefilter typefilter : typefiltersfor(filter)) {scanner.addincludefilter(typefilter);}}for (annotationattributes filter : componentscan.getannotationarray("excludefilters")) {for (typefilter typefilter : typefiltersfor(filter)) {scanner.addexcludefilter(typefilter);}}boolean lazyinit = componentscan.getboolean("lazyinit");if (lazyinit) {scanner.getbeandefinitiondefaults().tlazyinit(true);}t<string> bapackages = new linkedhasht<>();string[] bapackagesarray = componentscan.getstringarray("bapackages");for (string pkg : bapackagesarray) {string[] tokenized = stringutils.tokenizetostringarray(this.environment.resolveplaceholders(pkg),configurableapplicationcontext.config_location_delimiters);collections.addall(bapackages, tokenized);}for (class<?> clazz : componentscan.getclassarray("bapackageclass")) {bapackages.add(classutils.getpackagename(clazz));}if (bapackages.impty()) {bapackages.add(classutils.getpackagename(declaringclass));}scanner.addexcludefilter(new abstracttypehierarchytraversingfilter(fal, fal) {@overrideprotected boolean matchclassname(string classname) {return declaringclass.equals(classname);}});// 开始扫描return scanner.doscan(stringutils.tostringarray(bapackages));}

可以发现注解的扫描最后会调用classpathbeandefinitionscanner#doscan(),与xml中的扫描是同一个方法。

总结

xml的扫描过程发生在obtainfreshbeanfactory(),也就是创建beanfactory时,而注解的扫描过程发生在invokebeanfactorypostprocessors()。xml的扫描会在obtainfreshbeanfactory()时注入configurationclasspostprocessor,而注解的扫描是在创建annotationconfigapplicationcontext实例时注入configurationclasspostprocessor,如果xml扫描到的类带有@componentscan注解,那么还会继续在invokebeanfactorypostprocessors()阶段继续扫描。

到此这篇关于springcomponentscan的扫描过程的文章就介绍到这了,更多相关springcomponentscan扫描内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

本文发布于:2023-04-06 03:56:38,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/d34f880cd4ef4ba6cebc9d61dd7411e0.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:Spring ComponentScan的扫描过程解析.doc

本文 PDF 下载地址:Spring ComponentScan的扫描过程解析.pdf

标签:注解   过程   方法   扫描器
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图
  • 我要关灯
    我要开灯
  • 返回顶部