原文地址程序员囧辉大佬

相关文章

Spring IOC系列学习笔记一:前置刷新
Spring IOC系列学习笔记二:obtainFreshBeanFactory方法
Spring IOC系列学习笔记三:parseDefaultElement详解
Spring IOC系列学习笔记四:parseCustomElement解析
Spring IOC系列学习笔记五:context:component-scan 节点解析
Spring IOC系列学习笔记六:invokeBeanFactoryPostProcessors解析
Spring IOC系列学习笔记七:registerBeanPostProcessors
Spring IOC系列学习笔记八:finishBeanFactoryInitialization
Spring IOC系列学习笔记九:getBean方法
Spring IOC系列学习笔记十:createBean方法(上)
Spring IOC系列学习笔记十一:createBean方法(下)
Spring IOC系列学习笔记十二:@Autowire注解

文章目录

  • 相关文章
  • 前言
  • 代码块一:parse
  • 代码块二:configureScanner
  • 代码块三:createScanner
  • 代码块四:registerDefaultFilters
  • 代码块五:parseTypeFilters
  • 代码块六:doScan
  • 代码块七:findCandidateComponents
  • 代码块八:scanCandidateComponents
  • 代码块九:resolveScopeMetadata
  • 代码块十:postProcessBeanDefinition
  • 代码块十一:processCommonDefinitionAnnotations
  • 代码块十二:checkCandidate
  • 代码块十三:applyScopedProxyMode
  • 代码块十四:createScopedProxy
  • 代码块十五:registerComponents
  • 代码块十六:registerAnnotationConfigProcessors
  • 代码块十七:registerPostProcessor
  • 总结

前言

前面我们已经介绍了自定义节点的解析。我们以context:component-scan 节点为例子进行讲解。在findParserForElement方法后返回的是ComponentScanBeanDefinitionParser类,在该类中进行解析。

代码块一:parse

 @Override@Nullablepublic BeanDefinition parse(Element element, ParserContext parserContext) {1、获取base-package标签地址String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);1.1、解决占位符basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);1.3、分割,号成数组String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);// Actually scan for bean definitions and register them.2、把节点封装成ClassPathBeanDefinitionScanner供以后解析ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);3、扫描配置的包下面的地址,返回已经解析的beanSet<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);4、注册组件(包括注册一些内部的注解后置处理器、触发注册事件)registerComponents(parserContext.getReaderContext(), beanDefinitions, element);return null;}

2、把节点封装成ClassPathBeanDefinitionScanner供以后解析代码块二
3、扫描配置的包下面的地址,返回已经解析的bean见代码块六
4、注册组件(包括注册一些内部的注解后置处理器、触发注册事件)见代码块十五

代码块二:configureScanner

protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {1、使用默认的过滤器,也可以自己配置boolean useDefaultFilters = true;if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));}// Delegate bean definition registration to scanner class.2、将bean定义委托给ClassPathBeanDefinitionScannerClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());3、解析resource-patternif (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));}try {4、解析 name-generatorparseBeanNameGenerator(element, scanner);}catch (Exception ex) {parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());}try {5、解析ScopeparseScope(element, scanner);}catch (Exception ex) {parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());}6、解析类型过滤器属性parseTypeFilters(element, scanner, parserContext);return scanner;}

2、将bean定义委托给ClassPathBeanDefinitionScanner见代码块三
6、解析类型过滤器属性代码块五
其他方法不做解析,都大同小异,就是解析配置的各个属性

代码块三:createScanner

 protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters,readerContext.getEnvironment(), readerContext.getResourceLoader());}public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,Environment environment, @Nullable ResourceLoader resourceLoader) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");this.registry = registry;if (useDefaultFilters) {1、注册默认的过滤器registerDefaultFilters();}setEnvironment(environment);setResourceLoader(resourceLoader);}

1、注册默认的过滤器见代码块四

代码块四:registerDefaultFilters

     protected void registerDefaultFilters() {1、@Component放入缓存this.includeFilters.add(new AnnotationTypeFilter(Component.class));ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();try {2、@ManagedBean放入缓存this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));logger.debug("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 {3、@Named放入缓存this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-330 API not available - simply skip.}}

该方法执行完之后,includeFilters缓存中只会有@Component这一个注解,因为另外两个new AnnotationTypeFilter()会抛出异常,而没有加入到缓存当中。

代码块五:parseTypeFilters

 protected void parseTypeFilters(Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext) {// Parse exclude and include filter elements.ClassLoader classLoader = scanner.getResourceLoader().getClassLoader();1、获得所有的子节点 例如: <context:exclude-filter type="regex" expression="aaa"/>NodeList nodeList = element.getChildNodes();for (int i = 0; i < nodeList.getLength(); i++) {Node node = nodeList.item(i);if (node.getNodeType() == Node.ELEMENT_NODE) {2、拿到节点的name例如节点:<context:exclude-filter type="" expression=""/>,localName为:exclude-filterString localName = parserContext.getDelegate().getLocalName(node);try {if (INCLUDE_FILTER_ELEMENT.equals(localName)) {3.1、创建TypeFilterTypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);3.2、添加到scanner中scanner.addIncludeFilter(typeFilter);}else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) {4.1、创建TypeFilterTypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);4.2、添加到scanner中scanner.addExcludeFilter(typeFilter);}}catch (Exception ex) {parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());}}}}protected TypeFilter createTypeFilter(Element element, @Nullable ClassLoader classLoader, ParserContext parserContext) {5、获取type的值String filterType = element.getAttribute(FILTER_TYPE_ATTRIBUTE);6、获取expression的值String expression = element.getAttribute(FILTER_EXPRESSION_ATTRIBUTE);expression = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(expression);try {5.1、根据不同的filterType返回不同的实例,比如annotation返回AnnotationTypeFilterif ("annotation".equals(filterType)) {return new AnnotationTypeFilter((Class<Annotation>) ClassUtils.forName(expression, classLoader));}5.2、指定过滤的类或接口, 包括子类和子接口, expression为类全名称else if ("assignable".equals(filterType)) {return new AssignableTypeFilter(ClassUtils.forName(expression, classLoader));}5.3、 指定aspectj表达式来过滤类, expression为aspectj表达式字符串else if ("aspectj".equals(filterType)) {return new AspectJTypeFilter(expression, classLoader);}5.4、正则表达式 expression为表达式else if ("regex".equals(filterType)) {return new RegexPatternTypeFilter(Pattern.compile(expression));}5.5、用户自定义过滤器类型, expression为自定义过滤器的类全名称else if ("custom".equals(filterType)) {Class<?> filterClass = ClassUtils.forName(expression, classLoader);if (!TypeFilter.class.isAssignableFrom(filterClass)) {throw new IllegalArgumentException("Class is not assignable to [" + TypeFilter.class.getName() + "]: " + expression);}return (TypeFilter) BeanUtils.instantiateClass(filterClass);}else {throw new IllegalArgumentException("Unsupported filter type: " + filterType);}}catch (ClassNotFoundException ex) {throw new FatalBeanException("Type filter class not found: " + expression, ex);}}

configureScanner方法解析完毕,下面回到代码块一:3开始进入扫描doScan方法。

代码块六:doScan

 protected Set<BeanDefinitionHolder> doScan(String... basePackages) {Assert.notEmpty(basePackages, "At least one base package must be specified");Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();for (String basePackage : basePackages) {1、扫描basePackage,将符合要求的bean定义全部找出来Set<BeanDefinition> candidates = findCandidateComponents(basePackage);for (BeanDefinition candidate : candidates) {2、解析@Scope属性ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);candidate.setScope(scopeMetadata.getScopeName());3、根据beanName生成beanNameString beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);if (candidate instanceof AbstractBeanDefinition) {4、进一步解析beanpostProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);}if (candidate instanceof AnnotatedBeanDefinition) {5、处理定义在目标类上的通用注解,包括@Lazy, @Primary, @DependsOn, @Role, @DescriptionAnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);}6、检查bean是否注册过,检查是否兼容if (checkCandidate(beanName, candidate)) {BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);definitionHolder =7、根据proxyMode的值(步骤4中解析), 选择是否创建作用域代理AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);beanDefinitions.add(definitionHolder);8、注册bean到缓存中(注册到beanDefinitionMap、beanDefinitionNames、aliasMap缓存)前面已经解析过registerBeanDefinition(definitionHolder, this.registry);}}}return beanDefinitions;}

1、扫描basePackage见代码块七
2、解析Scope属性见代码块九
4、进一步解析bean见代码块十
5、处理定义在目标类上的通用注解见代码块十一
6、检查bean是否注册过,检查是否兼容见代码块十二
7、根据proxyMode的值见代码块十三
8、注册bean到缓存中已经解析过见Spring系列学习笔记三:代码块十四

代码块七:findCandidateComponents

     public Set<BeanDefinition> findCandidateComponents(String basePackage) {1、从索引中获取候选的bean 例:@Indexed  这是spring5推出的新的注解 目前没用过不熟悉if (this.componentsIndex != null && indexSupportsIncludeFilters()) {return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);}else {2、扫描候选组件return scanCandidateComponents(basePackage);}}

2、扫描候选组件见代码块八

代码块八:scanCandidateComponents

 private Set<BeanDefinition> scanCandidateComponents(String basePackage) {Set<BeanDefinition> candidates = new LinkedHashSet<>();try {1、要扫描的路径:例:classpath*:com/zgf/**/*.classString packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +resolveBasePackage(basePackage) + '/' + this.resourcePattern;2、扫描出该路径下所有的资源Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);boolean traceEnabled = logger.isTraceEnabled();boolean debugEnabled = logger.isDebugEnabled();for (Resource resource : resources) {if (traceEnabled) {logger.trace("Scanning " + resource);}if (resource.isReadable()) {try {3、用MetadataReader访问该元数据MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);4、判断是否是候选bean,就是用includeFilters和excludeFilters进行判断一下。if (isCandidateComponent(metadataReader)) {ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);sbd.setResource(resource);sbd.setSource(resource);5、二次判断判断是否是候选类if (isCandidateComponent(sbd)) {if (debugEnabled) {logger.debug("Identified candidate component class: " + resource);}6、确定是候选类,则添加到candidatescandidates.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 (Throwable ex) {throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, ex);}}else {if (traceEnabled) {logger.trace("Ignored because not readable: " + resource);}}}}catch (IOException ex) {throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);}return candidates;}4、判断是否是候选beanprotected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {for (TypeFilter tf : this.excludeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return false;}}for (TypeFilter tf : this.includeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return isConditionMatch(metadataReader);}}return false;}5、二次判断判断是否是候选类protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {AnnotationMetadata metadata = beanDefinition.getMetadata();(是否独立&&(具体的实现||(抽象&&@Lookup注解)))return (metadata.isIndependent() && (metadata.isConcrete() ||(metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));}

findCandidateComponents方法结束 回到代码块六,开始解析Scop属性见代码块九

代码块九:resolveScopeMetadata

@Override
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);// 如果使用了@Scope注解if (attributes != null) {// 解析scopeName属性metadata.setScopeName(attributes.getString("value"));// 解析proxyMode属性ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");if (proxyMode == null || proxyMode == ScopedProxyMode.DEFAULT) {proxyMode = this.defaultProxyMode;}metadata.setScopedProxyMode(proxyMode);}}return metadata;
}

如果使用了@Scope注解,则解析注解的属性。这边的 defaultProxyMode 取决于代码块1中步骤5的 scope-resolver、scoped-proxy 属性,默认为 ScopedProxyMode.NO。可以通过 scoped-proxy 来设置,例如下面配置 defaultProxyMode 的值就为 ScopedProxyMode.TARGET_CLASS。回到代码块六,进入postProcessBeanDefinition方法

    <context:component-scan  scoped-proxy="targetClass"  base-package="com.zgf">  </context:component-scan>

代码块十:postProcessBeanDefinition

protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {// 给beanDefinition设置默认值beanDefinition.applyDefaults(this.beanDefinitionDefaults);if (this.autowireCandidatePatterns != null) {// 设置此bean是否可以自动装配到其他bean中, 默认为truebeanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName));}
}

代码块十一:processCommonDefinitionAnnotations

public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {processCommonDefinitionAnnotations(abd, abd.getMetadata());}static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {1、@Lazy设置是否开启懒加载模式AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);if (lazy != null) {abd.setLazyInit(lazy.getBoolean("value"));}else if (abd.getMetadata() != metadata) {lazy = attributesFor(abd.getMetadata(), Lazy.class);if (lazy != null) {abd.setLazyInit(lazy.getBoolean("value"));}}2、@Primary当有多个bean匹配时候,用@Primary来区分同@Autowired和@Quealifier组合if (metadata.isAnnotated(Primary.class.getName())) {abd.setPrimary(true);}3、@DependsOn注解AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);if (dependsOn != null) {abd.setDependsOn(dependsOn.getStringArray("value"));}if (abd instanceof AbstractBeanDefinition) {AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;4、@Role注解AnnotationAttributes role = attributesFor(metadata, Role.class);if (role != null) {absBd.setRole(role.getNumber("value").intValue());}5、@Description注解AnnotationAttributes description = attributesFor(metadata, Description.class);if (description != null) {absBd.setDescription(description.getString("value"));}}}

回到代码块六继续解析。

代码块十二:checkCandidate

 protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {1、判断是否已经注册过,如果没注册则返回true,开始注册if (!this.registry.containsBeanDefinition(beanName)) {return true;}2、获取注册的bean实例BeanDefinition existingDef = this.registry.getBeanDefinition(beanName);BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition();if (originatingDef != null) {3、将新的实例替换为原来注册的实例existingDef = originatingDef;}4、判断新的是否与旧的兼容,如果不兼容抛出异常,兼容返回false跳过注册if (isCompatible(beanDefinition, existingDef)) {return false;}throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName +"' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " +"non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]");}

代码块十三:applyScopedProxyMode

static BeanDefinitionHolder applyScopedProxyMode(ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();// 1.如果不需要创建代理,则直接返回bean定义if (scopedProxyMode.equals(ScopedProxyMode.NO)) {return definition;}// 2.判断是使用基于类的代理还是基于接口的代码, 基于类: 使用CGLIB代理, 基于接口: 使用JDK动态代理boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);// 3.使用相应的代理模式, 创建一个scope代理return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}

3.使用相应的代理模式, 创建一个scope代理见代码块十四

代码块十四:createScopedProxy

 public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);}public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,BeanDefinitionRegistry registry, boolean proxyTargetClass) {1、获取原始的beanNameString originalBeanName = definition.getBeanName();2、原始的bean定义BeanDefinition targetDefinition = definition.getBeanDefinition();3、生成一个代理的bean名字String targetBeanName = getTargetBeanName(originalBeanName);// Create a scoped proxy definition for the original bean name,// "hiding" the target bean in an internal target definition.RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));4、设置代理bean的原始属性值proxyDefinition.setOriginatingBeanDefinition(targetDefinition);proxyDefinition.setSource(definition.getSource());proxyDefinition.setRole(targetDefinition.getRole());proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);if (proxyTargetClass) {5、根据类做代理targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);// ScopedProxyFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.}else {6、根据接口做代理proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);}// Copy autowire settings from original bean definition.7、从原始bean定义复制autowire设置proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());proxyDefinition.setPrimary(targetDefinition.isPrimary());if (targetDefinition instanceof AbstractBeanDefinition) {proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);}// The target bean should be ignored in favor of the scoped proxy.targetDefinition.setAutowireCandidate(false);targetDefinition.setPrimary(false);8、注册原始bean// Register the target bean as separate bean in the factory.registry.registerBeanDefinition(targetBeanName, targetDefinition);9、将代理bean封装成BeanDefinitionHolder对象并返回// Return the scoped proxy definition as primary bean definition// (potentially an inner bean).return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());}

回到代码块六开始注册bean。

代码块十五:registerComponents

protected void registerComponents(XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {Object source = readerContext.extractSource(element);// 1.使用注解的tagName(例如: context:component-scan)和source 构建CompositeComponentDefinitionCompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);// 2.将扫描到的所有BeanDefinition添加到compositeDef的nestedComponents属性中for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));}// Register annotation config processors, if necessary.boolean annotationConfig = true;if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {// 3.获取component-scan标签的annotation-config属性值(默认为true)annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));}if (annotationConfig) {// 4.如果annotation-config属性值为true,在给定的注册表中注册所有用于注解的Bean后置处理器Set<BeanDefinitionHolder> processorDefinitions =AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);for (BeanDefinitionHolder processorDefinition : processorDefinitions) {// 5.将注册的注解后置处理器的BeanDefinition添加到compositeDef的nestedComponents属性中compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));}}// 6.触发组件注册事件,默认实现为EmptyReaderEventListener(空实现,没有具体操作)readerContext.fireComponentRegistered(compositeDef);
}

4.在给定的注册表中注册所有用于注解的 bean 后置处理器,见代码块十六详解。

代码块十六:registerAnnotationConfigProcessors

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, Object source) {DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);if (beanFactory != null) {if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {// 1.设置dependencyComparator属性beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);}if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {// 2.设置autowireCandidateResolver属性(设置自动注入候选对象的解析器,用于判断BeanDefinition是否为候选对象)beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());}}Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);// 3.注册内部管理的用于处理@Configuration注解的后置处理器的beanif (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);// 3.1 registerPostProcessor: 注册BeanDefinition到注册表中beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));}// 4.注册内部管理的用于处理@Autowired、@Value、@Inject以及@Lookup注解的后置处理器的beanif (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}// 5.注册内部管理的用于处理@Required注解的后置处理器的beanif (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}// 6.注册内部管理的用于处理JSR-250注解(例如@Resource, @PostConstruct, @PreDestroy)的后置处理器的bean// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));}// 7.注册内部管理的用于处理JPA注解的后置处理器的bean// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition();try {def.setBeanClass(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.setSource(source);beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));}// 8.注册内部管理的用于处理@EventListener注解的后置处理器的beanif (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));}// 9.注册内部管理用于生产ApplicationListener对象的EventListenerFactory对象if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));}return beanDefs;
}

3.1 注册后置处理器的 BeanDefinition 到注册表中见代码块十七

代码块十七:registerPostProcessor

private static BeanDefinitionHolder registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {// 1.设置roledefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);// 2.注册BeanDefinitionregistry.registerBeanDefinition(beanName, definition);// 3.封装成BeanDefinitionHolder并返回return new BeanDefinitionHolder(definition, beanName);
}

至此,context:component-scan 节点解析已经完成,主要做的事情有:

  • 扫描 base-package 目录,将使用了 @Component、@Controller、@Repository、@Service
    注解的 bean
    注册到注册表中(其实就是beanDefinitionMap、beanDefinitionNames、aliasMap缓存中),跟之前解析默认命名空间一样,也是在后续创建
    bean 时需要使用这些缓存。
  • 添加了几个内部的注解相关的后置处理器:ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor
    等。

总结

同时,本文的结束,也标志着 obtainFreshBeanFactory 方法的详解正式结束。

简单来说,有以下几个主要操作:

  • 根据 web.xml 中 contextConfigLocation 配置的路径,读取 Spring 配置文件,并封装成
    Resource。

  • 根据 Resource 加载 XML 配置文件,并解析成 Document 对象 。

  • 拿到 Document 中的根节点,遍历根节点和所有子节点。

  • 根据命名空间,进行不同的解析,将 bean 节点内容解析成 BeanDefinition。

  • 将 BeanDefinition 注册到注册表中(也就是beanDefinitionMap、beanDefinitionNames、aliasMap缓存)。

执行完 obtainFreshBeanFactory 方法,我们得到了三个重要的对象:

  • 新的 BeanFactory。
  • beanDefinitionNames 缓存。
  • beanDefinitionMap 缓存。
    这三个对象在之后的 IoC 构建过程中会发挥重要的作用。

Spring IOC系列学习笔记五:context:component-scan 节点解析相关推荐

  1. 【Spring】Spring IOC学习笔记

    Spring IOC Spring简介 Spring理念 使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架 Spring优点 Spring是一个轻量级的 控制反转(IOC) 和 面向切 ...

  2. Spring Ioc 源码分析(一)- XML 解析

    2019独角兽企业重金招聘Python工程师标准>>> 注 :源码对应版本为 4.2.8.RELEASE 引入Spring依赖的时候,是否发现spring依赖有spring-bean ...

  3. 关于刘冬大侠Spring.NET系列学习笔记3的一点勘正

    诚如他第22楼"只因渴求等待"提出的疑问一样,他的下面那一段代码是存在一点点问题的, XElement root = XElement.Load(fileName);var obj ...

  4. spring IOC 之篇三:默认标签的解析

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {// 对import标签的处 ...

  5. Mr.J-- jQuery学习笔记(五)--属性及属性节点

    什么是属性? 对象身上保存的变量就是属性 如何操作属性? 对象.属性名称 = 值; 对象.属性名称; 对象["属性名称"] = 值; 对象["属性名称"]; 什 ...

  6. 注解Annotation的IoC:从@Autowired到@Component

    注解Annotation的IoC:从@Autowired到@Component 2017-01-23 目录 1 什么是注解 2 不使用注解示例   2.1 com.springioc.animal.M ...

  7. Spring IOC流程源码分析

    一.Spring 核心容器 IOC初始化过程 Spring 核心之 IOC 容器初体验 IOC 与 DI IOC(Inversion of Control)控制反转:所谓控制反转,就是把原先我们代码里 ...

  8. 21.手绘Spring IOC运行时序图

    1.再谈IOC与 DI IOC(lnversion of Control)控制反转:所谓控制反转,就是把原先我们代码里面需要实现的对象创 建.依赖的代码,反转给容器来帮忙实现.那么必然的我们需要创建一 ...

  9. 一步一步手绘Spring IOC运行时序图二(基于XML的IOC容器初始化)

    相关内容: 架构师系列内容:架构师学习笔记(持续更新) 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程) 一步一步手绘Spring IOC运行时序图二(基于XM ...

最新文章

  1. CodeSmith 学习资料收集
  2. 03-2 BGP专有命令--BGP命令与配置手册
  3. python面向对象设计模式_python面向对象之设计模式
  4. STL中容器的介绍及分类
  5. cx_Oracle库导入失败引起crontab中python程序运行失败,并且无错误提示
  6. Perl 语言入门学习
  7. bios 昂达h61c_Onda昂达主板BIOS,ONDA昂达H61N全固版(ver 3.00)主板BIOS 3.02版,主板BIOS,硬件驱动下载...
  8. Java后端技术知识点汇总(思维导图)
  9. Android中OKHttp的基本用法(Get、Post、上传文件等)
  10. 如何恢复Windows自动更新?
  11. 线性代数笔记4.3 齐次线性方程组
  12. 在wine里面播放视频和音乐之WMP
  13. oracle form视频,深入浅出Oracle 之Form开发
  14. iOS之Category和Extention的区别
  15. 微信JSAPI支付调不起收银台问题
  16. 辞旧送吉虎,迎新接玉兔,祝大家新年快乐!
  17. APIO2014 连珠线
  18. 实验四-1:输入一个字符,请判断是字母、数字还是其它字符。
  19. 订单23系统服务器,第3节芙拉吉尔 订单No23.系统服务器 死亡搁浅图文攻略 订单流程+设施介绍+道具介绍+界面操作_游侠网...
  20. 【转】关于IE7 z-index问题完美解决方案

热门文章

  1. 什么是外贸VPS主机?
  2. 毕业多年公英计算机考试,公英预测卷一
  3. [转]第一次考CCIE FAIL的经历……………
  4. Altium Designer--如何制作过孔(Via)库
  5. 全新版PS色环插件Coolorus,支持PSCS6-CC2022
  6. 一步步教你怎么用Python写贪吃蛇游戏
  7. Oracle表空间系列
  8. 2018ACM暑期多校联合训练参(bao)赛(zha)记
  9. 围棋,人vs人(自行判断输赢)
  10. 程序员:孤独的人是可耻的!