Skip to content

Latest commit

 

History

History
512 lines (430 loc) · 19.9 KB

Spring-scan.md

File metadata and controls

512 lines (430 loc) · 19.9 KB

Spring scan

解析

  • Spring 注解形式使用有下面两种方式
    1. 通过AnnotationConfigApplicationContext参数:扫描包
    2. 通过 xml 配置context:component-scan属性base-package
AnnotationConfigApplicationContextaac = newAnnotationConfigApplicationContext("com.huifer.source.spring.ann");
 <context:component-scanbase-package="com.huifer.source.spring.ann"> </context:component-scan>
  • 目标明确开始找入口方法
  • AnnotationConfigApplicationContext直接点进去看就找到了
publicAnnotationConfigApplicationContext(String... basePackages) { this(); // 扫描包scan(basePackages); refresh(); }
  • context:component-scan寻找方式:冒号:钱+NamespaceHandler 或者全文搜索component-scan,最终找到org.springframework.context.config.ContextNamespaceHandler
publicclassContextNamespaceHandlerextendsNamespaceHandlerSupport { @Overridepublicvoidinit() { registerBeanDefinitionParser("property-placeholder", newPropertyPlaceholderBeanDefinitionParser()); registerBeanDefinitionParser("property-override", newPropertyOverrideBeanDefinitionParser()); registerBeanDefinitionParser("annotation-config", newAnnotationConfigBeanDefinitionParser()); registerBeanDefinitionParser("component-scan", newComponentScanBeanDefinitionParser()); registerBeanDefinitionParser("load-time-weaver", newLoadTimeWeaverBeanDefinitionParser()); registerBeanDefinitionParser("spring-configured", newSpringConfiguredBeanDefinitionParser()); registerBeanDefinitionParser("mbean-export", newMBeanExportBeanDefinitionParser()); registerBeanDefinitionParser("mbean-server", newMBeanServerBeanDefinitionParser()); } }

org.springframework.context.annotation.ComponentScanBeanDefinitionParser

image-20200115093602651

  • 实现BeanDefinitionParser直接看parse方法
@Override@NullablepublicBeanDefinitionparse(Elementelement, ParserContextparserContext) { // 获取 base-package 属性值StringbasePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); // 处理 ${}basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); // 分隔符`,;\t\n`切分String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); // Actually scan for bean definitions and register them.// 扫描对象创建ClassPathBeanDefinitionScannerscanner = configureScanner(parserContext, element); // 执行扫描方法Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); // 注册组件,触发监听registerComponents(parserContext.getReaderContext(), beanDefinitions, element); returnnull; }
  • 回过头看AnnotationConfigApplicationContext

org.springframework.context.annotation.AnnotationConfigApplicationContext

publicAnnotationConfigApplicationContext(String... basePackages) { this(); // 扫描包scan(basePackages); refresh(); }
privatefinalClassPathBeanDefinitionScannerscanner; @Overridepublicvoidscan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); this.scanner.scan(basePackages); }
  • org.springframework.context.annotation.ClassPathBeanDefinitionScanner.scan
publicintscan(String... basePackages) { // 获取bean数量intbeanCountAtScanStart = this.registry.getBeanDefinitionCount(); // 执行扫描doScan(basePackages); // Register annotation config processors, if necessary.if (this.includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart); }
  • 这个地方doScan似曾相识,他就是org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse中的doScan,下一步解析 doScan

org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan

protectedSet<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = newLinkedHashSet<>(); for (StringbasePackage : basePackages) { // 寻找组件Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinitioncandidate : candidates) { // bean 作用域设置ScopeMetadatascopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); // 设置生命周期candidate.setScope(scopeMetadata.getScopeName()); // 创建beanNameStringbeanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidateinstanceofAbstractBeanDefinition) { // 设置默认属性 具体方法:org.springframework.beans.factory.support.AbstractBeanDefinition.applyDefaultspostProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidateinstanceofAnnotatedBeanDefinition) { // 读取Lazy,Primary 等注解AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } // bean的重复检查if (checkCandidate(beanName, candidate)) { // 创建 BeanDefinitionHolderBeanDefinitionHolderdefinitionHolder = newBeanDefinitionHolder(candidate, beanName); // 代理对象的处理definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); // 放入list中,最后返回用beanDefinitions.add(definitionHolder); // 注册beanregisterBeanDefinition(definitionHolder, this.registry); } } } returnbeanDefinitions; }

org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents

publicSet<BeanDefinition> findCandidateComponents(StringbasePackage) { // 扫描if (this.componentsIndex != null && indexSupportsIncludeFilters()) { returnaddCandidateComponentsFromIndex(this.componentsIndex, basePackage); } else { returnscanCandidateComponents(basePackage); } }
/** * 扫描当前包路径下的资源 * @param basePackage * @return */privateSet<BeanDefinition> scanCandidateComponents(StringbasePackage) { Set<BeanDefinition> candidates = newLinkedHashSet<>(); try { // 字符串拼接出一个编译后的路径 classpath://// 这里替换了通配符StringpackageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; // 获取资源Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); // 日志级别booleantraceEnabled = logger.isTraceEnabled(); booleandebugEnabled = logger.isDebugEnabled(); for (Resourceresource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) { try { // 获取 MetadataReaderMetadataReadermetadataReader = getMetadataReaderFactory().getMetadataReader(resource); // 判断是否是 Componentif (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinitionsbd = newScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { if (traceEnabled) { logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwableex) { thrownewBeanDefinitionStoreException( "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { logger.trace("Ignored because not readable: " + resource); } } } } catch (IOExceptionex) { thrownewBeanDefinitionStoreException("I/O failure during classpath scanning", ex); } returncandidates; }

org.springframework.context.annotation.ScopeMetadataResolver#resolveScopeMetadata

/** * 生命周期设置 * * @param definition the target bean definition * @return */@OverridepublicScopeMetadataresolveScopeMetadata(BeanDefinitiondefinition) { ScopeMetadatametadata = newScopeMetadata(); // 判断是否属于 AnnotatedBeanDefinitionif (definitioninstanceofAnnotatedBeanDefinition) { AnnotatedBeanDefinitionannDef = (AnnotatedBeanDefinition) definition; AnnotationAttributesattributes = AnnotationConfigUtils.attributesFor( annDef.getMetadata(), this.scopeAnnotationType); if (attributes != null) { // 获取 value 属性值并且设置metadata.setScopeName(attributes.getString("value")); // 获取 proxyMode 属性值并且设置ScopedProxyModeproxyMode = attributes.getEnum("proxyMode"); if (proxyMode == ScopedProxyMode.DEFAULT) { proxyMode = this.defaultProxyMode; } metadata.setScopedProxyMode(proxyMode); } } returnmetadata; } 
  • org.springframework.context.annotation.AnnotationScopeMetadataResolverTests#resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation测试用例
@TestpublicvoidresolveScopeMetadataShouldReadScopedProxyModeFromAnnotation() { AnnotatedBeanDefinitionbd = newAnnotatedGenericBeanDefinition(AnnotatedWithScopedProxy.class); ScopeMetadatascopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd); assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata); assertEquals("request", scopeMetadata.getScopeName()); assertEquals(TARGET_CLASS, scopeMetadata.getScopedProxyMode()); }

image-20200115141708702

org.springframework.beans.factory.support.BeanNameGenerator#generateBeanName

  • 创建 beanName org.springframework.context.annotation.AnnotationBeanNameGenerator#generateBeanName
@OverridepublicStringgenerateBeanName(BeanDefinitiondefinition, BeanDefinitionRegistryregistry) { if (definitioninstanceofAnnotatedBeanDefinition) { // 如果存在bean(value="") value存在StringbeanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition); if (StringUtils.hasText(beanName)) { // Explicit bean name found.returnbeanName; } } // Fallback: generate a unique default bean name.// 创建beanNamereturnbuildDefaultBeanName(definition, registry); }
@NullableprotectedStringdetermineBeanNameFromAnnotation(AnnotatedBeanDefinitionannotatedDef) { AnnotationMetadataamd = annotatedDef.getMetadata(); Set<String> types = amd.getAnnotationTypes(); StringbeanName = null; for (Stringtype : types) { AnnotationAttributesattributes = AnnotationConfigUtils.attributesFor(amd, type); if (attributes != null && isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) { // 获取注解的value 属性值Objectvalue = attributes.get("value"); if (valueinstanceofString) { StringstrVal = (String) value; // 判断是否存在值if (StringUtils.hasLength(strVal)) { if (beanName != null && !strVal.equals(beanName)) { thrownewIllegalStateException("Stereotype annotations suggest inconsistent " + "component names: '" + beanName + "' versus '" + strVal + "'"); } // beanName = value属性值beanName = strVal; } } } } returnbeanName; }
@Service(value = "dhc") publicclassDemoService { }

image-20200115143315633

  • org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.support.BeanDefinitionRegistry)
    • org.springframework.context.annotation.AnnotationBeanNameGenerator#buildDefaultBeanName(org.springframework.beans.factory.config.BeanDefinition)
protectedStringbuildDefaultBeanName(BeanDefinitiondefinition) { // 获取bean class nameStringbeanClassName = definition.getBeanClassName(); Assert.state(beanClassName != null, "No bean class name set"); // 获取短类名,StringshortClassName = ClassUtils.getShortName(beanClassName); // 第一个字母小写returnIntrospector.decapitalize(shortClassName); }
@ConfigurationpublicclassBeanConfig { @Scope(value =ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Bean(value = "hc") publicUbeanf() { returnnewUbean(); } }

image-20200115143456554

org.springframework.context.annotation.ClassPathBeanDefinitionScanner#postProcessBeanDefinition

  • 这个方法没什么难点,直接是 set 方法
protectedvoidpostProcessBeanDefinition(AbstractBeanDefinitionbeanDefinition, StringbeanName) { beanDefinition.applyDefaults(this.beanDefinitionDefaults); if (this.autowireCandidatePatterns != null) { beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName)); } }
publicvoidapplyDefaults(BeanDefinitionDefaultsdefaults) { setLazyInit(defaults.isLazyInit()); setAutowireMode(defaults.getAutowireMode()); setDependencyCheck(defaults.getDependencyCheck()); setInitMethodName(defaults.getInitMethodName()); setEnforceInitMethod(false); setDestroyMethodName(defaults.getDestroyMethodName()); setEnforceDestroyMethod(false); }

org.springframework.context.annotation.AnnotationConfigUtils#processCommonDefinitionAnnotations(org.springframework.beans.factory.annotation.AnnotatedBeanDefinition)

publicstaticvoidprocessCommonDefinitionAnnotations(AnnotatedBeanDefinitionabd) { processCommonDefinitionAnnotations(abd, abd.getMetadata()); }
staticvoidprocessCommonDefinitionAnnotations(AnnotatedBeanDefinitionabd, AnnotatedTypeMetadatametadata) { // 获取 lazy 注解AnnotationAttributeslazy = attributesFor(metadata, Lazy.class); if (lazy != null) { abd.setLazyInit(lazy.getBoolean("value")); } elseif (abd.getMetadata() != metadata) { lazy = attributesFor(abd.getMetadata(), Lazy.class); if (lazy != null) { abd.setLazyInit(lazy.getBoolean("value")); } } if (metadata.isAnnotated(Primary.class.getName())) { abd.setPrimary(true); } AnnotationAttributesdependsOn = attributesFor(metadata, DependsOn.class); if (dependsOn != null) { abd.setDependsOn(dependsOn.getStringArray("value")); } AnnotationAttributesrole = attributesFor(metadata, Role.class); if (role != null) { abd.setRole(role.getNumber("value").intValue()); } AnnotationAttributesdescription = attributesFor(metadata, Description.class); if (description != null) { abd.setDescription(description.getString("value")); } }
  • 方法思路:
    1. 获取注解的属性值
    2. 设置注解属性

org.springframework.context.annotation.ClassPathBeanDefinitionScanner#checkCandidate

  • 重复检查
protectedbooleancheckCandidate(StringbeanName, BeanDefinitionbeanDefinition) throwsIllegalStateException { // 判断当前 beanName 是否在注册表中if (!this.registry.containsBeanDefinition(beanName)) { returntrue; } // 从注册表中获取BeanDefinitionexistingDef = this.registry.getBeanDefinition(beanName); // 当前的beanBeanDefinitionoriginatingDef = existingDef.getOriginatingBeanDefinition(); if (originatingDef != null) { existingDef = originatingDef; } if (isCompatible(beanDefinition, existingDef)) { returnfalse; } thrownewConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName + "' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " + "non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]"); }

org.springframework.context.annotation.AnnotationConfigUtils#applyScopedProxyMode

staticBeanDefinitionHolderapplyScopedProxyMode( ScopeMetadatametadata, BeanDefinitionHolderdefinition, BeanDefinitionRegistryregistry) { ScopedProxyModescopedProxyMode = metadata.getScopedProxyMode(); if (scopedProxyMode.equals(ScopedProxyMode.NO)) { returndefinition; } booleanproxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS); // 创建代理对象returnScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass); }
close