前言java
本文轉自「天河聊技術」微信公衆號node
本次介紹ContextNamespaceHandler解析之annotation-config、component-scan正則表達式
正文spring
按照上一篇文章的方法找到這個方法express
org.springframework.beans.factory.xml.NamespaceHandlerSupport#parseapi
@Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { // 得到bean定義解析器 BeanDefinitionParser parser = findParserForElement(element, parserContext); return (parser != null ? parser.parse(element, parserContext) : null); }
進入到這個方法微信
org.springframework.context.annotation.AnnotationConfigBeanDefinitionParser#parseapp
@Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { Object source = parserContext.extractSource(element); // Obtain bean definitions for all relevant BeanPostProcessors.註冊註解處理器 Set<BeanDefinitionHolder> processorDefinitions = AnnotationConfigUtils.registerAnnotationConfigProcessors(parserContext.getRegistry(), source); // Register component for the surrounding <context:annotation-config> element. CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source); parserContext.pushContainingComponent(compDefinition); // Nest the concrete beans in the surrounding component. for (BeanDefinitionHolder processorDefinition : processorDefinitions) { parserContext.registerComponent(new BeanComponentDefinition(processorDefinition)); } // Finally register the composite component. parserContext.popAndRegisterContainingComponent(); return null; }
進入到這個方法ide
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null) { if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { // 依賴比較器是當即加載的到單例實現 beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(4); if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (!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)); } if (!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)); } // 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)); } // 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)); } if (!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)); } 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; }
這個標籤解析的時候註冊一些bean定義解析器。post
下面介紹component-scan解析
返回到這個方法
org.springframework.beans.factory.xml.NamespaceHandlerSupport#parse的最後一行代碼
@Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { // 得到bean定義解析器 BeanDefinitionParser parser = findParserForElement(element, parserContext); return (parser != null ? parser.parse(element, parserContext) : null); }
進入到這個方法
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#parse
@Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { // 獲取base-package屬性 String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); // 解析佔位符 basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); // 掃描的包能夠是多個用分隔符分開 String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); // Actually scan for bean definitions and register them. 掃描bean定義註冊 ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); // bean定義掃描 Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); // 註冊組件 registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; }
進入這個方法
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) { boolean useDefaultFilters = true; // 若是有這個use-default-filters屬性 使用默認的filter進行包掃描 if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) { useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)); } // Delegate bean definition registration to scanner class.建立bean定義掃描器 ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters); scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults()); // 設置自動裝配模式 scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns()); if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) { scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE)); } try { // 解析beanName生成器 parseBeanNameGenerator(element, scanner); } catch (Exception ex) { parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } try { // 解析bean的scope parseScope(element, scanner); } catch (Exception ex) { parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } parseTypeFilters(element, scanner, parserContext); return scanner; }
找到這行代碼
// Delegate bean definition registration to scanner class.建立bean定義掃描器 ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);
進入這個方法
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) { // 註冊默認的過濾器 registerDefaultFilters(); } setEnvironment(environment); setResourceLoader(resourceLoader); }
進入這個方法
protected void registerDefaultFilters() { // 註冊@Component類型的過濾器,只要帶有這個註解的bean定義都會被掃描,也包括包裝這個註解的註解 this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { // @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 { // @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. } }
返回到這個方法
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#configureScanner這一行代碼
// 解析beanName生成器 parseBeanNameGenerator(element, scanner);
進入這個方法
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#parseBeanNameGenerator
protected void parseBeanNameGenerator(Element element, ClassPathBeanDefinitionScanner scanner) { // 獲取這個屬性name-generator,若是沒有指定beanName生成器就用AnnotationBeanNameGenerator這個 if (element.hasAttribute(NAME_GENERATOR_ATTRIBUTE)) { BeanNameGenerator beanNameGenerator = (BeanNameGenerator) instantiateUserDefinedStrategy( element.getAttribute(NAME_GENERATOR_ATTRIBUTE), BeanNameGenerator.class, scanner.getResourceLoader().getClassLoader()); scanner.setBeanNameGenerator(beanNameGenerator); } }
返回到這個方法這一行代碼
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#configureScanner
// 解析bean的scope parseScope(element, scanner);
進入這個方法
protected void parseScope(Element element, ClassPathBeanDefinitionScanner scanner) { // Register ScopeMetadataResolver if class name provided. if (element.hasAttribute(SCOPE_RESOLVER_ATTRIBUTE)) { if (element.hasAttribute(SCOPED_PROXY_ATTRIBUTE)) { throw new IllegalArgumentException( "Cannot define both 'scope-resolver' and 'scoped-proxy' on <component-scan> tag"); } ScopeMetadataResolver scopeMetadataResolver = (ScopeMetadataResolver) instantiateUserDefinedStrategy( element.getAttribute(SCOPE_RESOLVER_ATTRIBUTE), ScopeMetadataResolver.class, scanner.getResourceLoader().getClassLoader()); scanner.setScopeMetadataResolver(scopeMetadataResolver); } // 獲取scoped-proxy屬性 if (element.hasAttribute(SCOPED_PROXY_ATTRIBUTE)) { String mode = element.getAttribute(SCOPED_PROXY_ATTRIBUTE); // cglib動態代理 if ("targetClass".equals(mode)) { scanner.setScopedProxyMode(ScopedProxyMode.TARGET_CLASS); } // jdk動態代理 else if ("interfaces".equals(mode)) { scanner.setScopedProxyMode(ScopedProxyMode.INTERFACES); } else if ("no".equals(mode)) { scanner.setScopedProxyMode(ScopedProxyMode.NO); } else { throw new IllegalArgumentException("scoped-proxy only supports 'no', 'interfaces' and 'targetClass'"); } } }
返回到這個方法org.springframework.context.annotation.ComponentScanBeanDefinitionParser#configureScanner這一行代碼
// 解析掃描過濾器 parseTypeFilters(element, scanner, parserContext);
進入這個方法
protected void parseTypeFilters(Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext) { // Parse exclude and include filter elements. ClassLoader classLoader = scanner.getResourceLoader().getClassLoader(); NodeList nodeList = element.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { String localName = parserContext.getDelegate().getLocalName(node); try { // include-filter節點 if (INCLUDE_FILTER_ELEMENT.equals(localName)) { // 建立類型過濾器 TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext); scanner.addIncludeFilter(typeFilter); } // exclude-filter節點 else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) { TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext); scanner.addExcludeFilter(typeFilter); } } catch (ClassNotFoundException ex) { parserContext.getReaderContext().warning( "Ignoring non-present type filter class: " + ex, parserContext.extractSource(element)); } catch (Exception ex) { parserContext.getReaderContext().error( ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } } } }
找到這個方法
建立類型過濾器 TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
進入建立包掃描過濾器這個方法
protected TypeFilter createTypeFilter(Element element, @Nullable ClassLoader classLoader, ParserContext parserContext) throws ClassNotFoundException { // 獲取type屬性 String filterType = element.getAttribute(FILTER_TYPE_ATTRIBUTE); // 獲取expression屬性 String expression = element.getAttribute(FILTER_EXPRESSION_ATTRIBUTE); expression = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(expression); // 註解類型 if ("annotation".equals(filterType)) { return new AnnotationTypeFilter((Class<Annotation>) ClassUtils.forName(expression, classLoader)); } // 指定類或接口的全名 else if ("assignable".equals(filterType)) { return new AssignableTypeFilter(ClassUtils.forName(expression, classLoader)); } // aspectj表達式 else if ("aspectj".equals(filterType)) { return new AspectJTypeFilter(expression, classLoader); } // 正則表達式 else if ("regex".equals(filterType)) { return new RegexPatternTypeFilter(Pattern.compile(expression)); } // TypeFilter自定義實現 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); } }
支持以上這幾種包掃描過濾器配置方式。
返回到這個方法這一行代碼
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#parse
// bean定義掃描 Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
進入這個方法
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#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) { Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { // 解析scope的metadata信息 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); // 解析beanName String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { // 解析通常的bean定義屬性 postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); // 註冊bean定義 registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
找到這一行代碼
// 解析beanName String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
找到這個方法
org.springframework.context.annotation.AnnotationBeanNameGenerator#generateBeanName
@Override public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { if (definition instanceof AnnotatedBeanDefinition) { // 從註解中獲取beanName 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); }
找到這行代碼
// 從註解中獲取beanName String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
從註解配置中獲取beanName
@Nullable protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) { AnnotationMetadata amd = annotatedDef.getMetadata(); Set<String> types = amd.getAnnotationTypes(); String beanName = null; for (String type : types) { AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type); if (attributes != null && isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) { Object value = attributes.get("value"); if (value instanceof String) { String strVal = (String) value; if (StringUtils.hasLength(strVal)) { if (beanName != null && !strVal.equals(beanName)) { throw new IllegalStateException("Stereotype annotations suggest inconsistent " + "component names: '" + beanName + "' versus '" + strVal + "'"); } beanName = strVal; } } } } return beanName; }
若是註解中沒有配置beanName,就自動生成beanName
return buildDefaultBeanName(definition, registry);
protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { return buildDefaultBeanName(definition); }
protected String buildDefaultBeanName(BeanDefinition definition) { String beanClassName = definition.getBeanClassName(); Assert.state(beanClassName != null, "No bean class name set"); String shortClassName = ClassUtils.getShortName(beanClassName); return Introspector.decapitalize(shortClassName); }
默認生成的beanName是類的簡單名稱
返回到這個方法org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan的這一行
// 解析通常的bean定義屬性 postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
// 解析通常的bean定義註解 AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
進入這個方法
org.springframework.context.annotation.AnnotationConfigUtils#processCommonDefinitionAnnotations(org.springframework.beans.factory.annotation.AnnotatedBeanDefinition, org.springframework.core.type.AnnotatedTypeMetadata)
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { // 解析lazy註解 AnnotationAttributes lazy = attributesFor(metadata, Lazy.class); if (lazy != null) { // 獲取value的屬性值是否開啓延遲加載 abd.setLazyInit(lazy.getBoolean("value")); } else if (abd.getMetadata() != metadata) { lazy = attributesFor(abd.getMetadata(), Lazy.class); if (lazy != null) { abd.setLazyInit(lazy.getBoolean("value")); } } // 獲取Primary註解值 if (metadata.isAnnotated(Primary.class.getName())) { abd.setPrimary(true); } // 解析DependsOn註解 AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class); if (dependsOn != null) { // 獲取value屬性值 abd.setDependsOn(dependsOn.getStringArray("value")); } if (abd instanceof AbstractBeanDefinition) { AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd; // 解析Role註解 AnnotationAttributes role = attributesFor(metadata, Role.class); if (role != null) { // 獲取value屬性值 absBd.setRole(role.getNumber("value").intValue()); } // 解析Description註解 AnnotationAttributes description = attributesFor(metadata, Description.class); if (description != null) { // 獲取value屬性值 absBd.setDescription(description.getString("value")); } } }
返回到這個方法org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan的這一行
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
static BeanDefinitionHolder applyScopedProxyMode( ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) { ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode(); // 若是沒有開啓動態代理,直接返回bean定義 if (scopedProxyMode.equals(ScopedProxyMode.NO)) { return definition; } // 若是是cglib動態代理 boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS); // 建立動態代理 return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass); }
返回到這個方法的這一行代碼
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#parse
@Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { // 獲取base-package屬性 String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); // 解析佔位符 basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); // 掃描的包能夠是多個用分隔符分開 String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); // Actually scan for bean definitions and register them. 掃描bean定義註冊 ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); // bean定義掃描 Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); // 註冊組件 registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; }
進入這個方法
protected void registerComponents( XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) { Object source = readerContext.extractSource(element); CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source); for (BeanDefinitionHolder beanDefHolder : beanDefinitions) { compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder)); } // Register annotation config processors, if necessary. boolean annotationConfig = true; // 節點有annotation-config屬性 if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) { annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE)); } if (annotationConfig) { Set<BeanDefinitionHolder> processorDefinitions = // 註冊註解解析器 AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source); for (BeanDefinitionHolder processorDefinition : processorDefinitions) { compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition)); } } // 出發組件註冊事件 readerContext.fireComponentRegistered(compositeDef); }
component-scan節點解析完了。
最後
本次介紹到這裏,以上內容僅供參考。