咱们在了解 Spring 容器的扩展功能 (ApplicationContext) 以前,先介绍下 context:component-scan
标签的解析过程,其做用很大是注解能生效的关键所在。html
咱们这次直接从 BeanDefinitionParseDelegate#parseCustomElement()
开始往下分析,不知道前面流程的能够看一下 [Spring XML Bean 定义的加载和注册](https://leisurexi.github.io/category/2020/04/14/Spring IoC/Spring XML Bean 定义的加载和注册.html) 这篇文章,以前的流程都有解析。java
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { // 获取自定义标签的命名空间 String namespaceUri = getNamespaceURI(ele); if (namespaceUri == null) { return null; } // 获取自定义标签的处理器,这里解析的是context:component-scan,因此获取的是ContextNamespaceHandler NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } // 进行标签的解析,见下文详解 return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }
public BeanDefinition parse(Element element, ParserContext parserContext) { // 获取属性basePacket的值 String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); // 解析占位符,例如${basePackage} basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); // 解析base-package(容许经过 ",; \t\n" 中的任一符号填写多个),例如: com.leisurexi.one;com.leisurexi.two String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); // Actually scan for bean definitions and register them. // 构建和配置ClassPathBeanDefinitionScanner,见下文详解 ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); // 使用scanner在指定的包路径进行扫描,返回注册后的BeanDefinition,见下文详解 Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); // 注册组件(包括一些内部注解的后置处理器),见下文详解 registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; }
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) { // 是否使用默认的过滤器,默认为true boolean useDefaultFilters = true; // 若是设置了use-default-filters属性,则使用设置的值 if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) { useDefaultFilters = Boolean.parseBoolean(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)); } // Delegate bean definition registration to scanner class. // 构建ClassPathBeanDefinitionScanner,将bean定义注册委托给scanner类,见下文详解 ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters); scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults()); scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns()); // 解析resource-pattern属性 if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) { scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE)); } try { // 解析name-generator属性 parseBeanNameGenerator(element, scanner); } catch (Exception ex) { parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } try { // 解析scope-resolver、scoped-proxy属性 parseScope(element, scanner); } catch (Exception ex) { parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } // 解析类型过滤器,见下文详解 parseTypeFilters(element, scanner, parserContext); return scanner; }
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) { return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters,readerContext.getEnvironment(), readerContext.getResourceLoader()); } // ClassPathBeanDefinitionScanner.java 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添加到includeFilters中,这将隐式的注册全部@Component的派生注解,例如@Repository、@Service、@Controller this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { // 若是当前环境中有@ManagedBean,添加到includeFilters中,不然会catch未找到类的异常并忽略 this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false)); 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 { // 若是当前环境中有@Named,添加到includeFilters中,不然会catch未找到类的异常并忽略 this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false)); logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. } }
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) { // 寻找包路径下符合要求的bean定义(最多见的就是使用@Component标注的类) Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { // 解析@Scope注解,没有标注默认为singleton做用域 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); // 生成bean的名称,见下文详解 String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { // beanDefinition的后置处理,就是设置beanDefinition的一些默认属性,如autowireMode、initMethod等,而且设置AutowireCandidate, // 通常为true表明能够自动装配到其余bean中 postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { // 处理公共注解,见下文详解 AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } // 若是beanDefinition经过检查(大多时候是检查是否是第一次注册),则将definitionHolder添加进注册中心中,若是有同名的bean在这里会直接抛出异常 if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
public Set<BeanDefinition> findCandidateComponents(String basePackage) { if (this.componentsIndex != null && indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); } else { // 扫描符合条件的组件 return scanCandidateComponents(basePackage); } } private Set<BeanDefinition> scanCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<>(); try { // 将要扫描的包的路径拼成完整的,例如:com.leisurexi.ioc.context 会被拼成 classpath*:com/leisurexi/ioc/context/**/*.class String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; // 获取路径下的全部类的资源 Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); for (Resource resource : resources) { // 若是资源是可读的 if (resource.isReadable()) { try { // 使用metadataReader读取资源,MetadataReader是专门用来访问元数据的类(包括: 类元数据ClassMetadata、注解元数据AnnotationMetadata等) MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); // 判断该类是否是候选的组件 if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); // 判断是不是候选组件,默认条件是class不是接口而且不依赖于内部类 if (isCandidateComponent(sbd)) { candidates.add(sbd); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, ex); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } return candidates; }
上面代码中判断该类是否是候选的组件的方法 isCandidateComponent(metadataReader)
通常状况下 是判断该类是否标注了上文中 ClassPathScanningCandidateComponentProvider#registerDefaultFilters()
中的注解 @Component
、@ManagedBean
、@Named
;@Component
注解是确定会存在与当前环境中的,因此标注了 @Component
或者其派生的注解如:@Repository
、@Service
、@Controller
都会被当作候选组件。git
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { // 若是BeanDefinition是AnnotatedBeanDefinition类型 if (definition instanceof AnnotatedBeanDefinition) { // 获取自定义的beanName,如 @Component注解的value值 String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition); // 若是不为空,而且不是空字符串 if (StringUtils.hasText(beanName)) { // Explicit bean name found. // 返回明确的beanName return beanName; } } // Fallback: generate a unique default bean name. // 没有手动指定beanName,默认生成一个,是当前类名的首字母小写,如User类的beanName是user return buildDefaultBeanName(definition, registry); }
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { // 若是bean标注了@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")); } } // 解析@Primary注解,自动装配时当出现多个Bean都匹配时,标注了@Primary注解的Bean将做为首选者 if (metadata.isAnnotated(Primary.class.getName())) { abd.setPrimary(true); } // 解析@DependsOn注解,代表当前bean须要依赖的bean,会保证依赖的bean会在当前bean前实例化 AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class); if (dependsOn != null) { abd.setDependsOn(dependsOn.getStringArray("value")); } // 解析@Role注解,用于标识bean的分类,实际用的比较少 AnnotationAttributes role = attributesFor(metadata, Role.class); if (role != null) { abd.setRole(role.getNumber("value").intValue()); } // 解析@Description注解,bean的描述,实际用的比较少 AnnotationAttributes description = attributesFor(metadata, Description.class); if (description != null) { abd.setDescription(description.getString("value")); } }
protected void registerComponents(XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) { Object source = readerContext.extractSource(element); CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source); // 将扫描的全部BeanDefinition添加到compositeDef中 for (BeanDefinitionHolder beanDefHolder : beanDefinitions) { compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder)); } // Register annotation config processors, if necessary. boolean annotationConfig = true; // 获取annotation-config属性,默认为true if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) { annotationConfig = Boolean.parseBoolean(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE)); } if (annotationConfig) { // 向注册中心中注册用于注解的后置处理器,如AutowireAnnotationProcessor、CommonAnnotationProcessor Set<BeanDefinitionHolder> processorDefinitions = AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source); // 将注册的注解后置处理器的BeanDefinition添加到compositeDef的nestedComponents属性中 for (BeanDefinitionHolder processorDefinition : processorDefinitions) { compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition)); } } // 触发注册事件,默认实现为EmptyReaderEventListener(空实现,没有具体操做) readerContext.fireComponentRegistered(compositeDef); }
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { // 获取beanFactory DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null) { if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { // 设置dependencyComparator属性 beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { // 设置autowireCandidateResolver属性(设置自动注入候选对象的解析器,用于判断BeanDefinition是否为候选对象) beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8); // 注册用于处理@Configuration注解的后置处理器 if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { // 建立一个ConfigurationClassPostProcessor的BeanDefinition RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); // 将def添加进注册中心 beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } // 注册用于处理@Autowired、@Value、@Inject注解的后置处理器 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)); } // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor. // 注册用于处理@Resource、@PostConstructor、@PostDestroy注解的后置处理器 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. // 注册用于处理JPA注解的后置处理器,如@PersistenceContext、@PersistenceUnit 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)); } // 注册用于处理@EventListener注解的后置处理器 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)); } // 注册内部管理用于生产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; }
本文主要介绍了 Spring 解析 context:component-scan
标签的解析流程,咱们能够从新整理一下思路:github
@Component
注解以及它的派生注解当作组件注册。BeanDefinition
;解析 @Scope
注解,没有默认为 singleton
;生成 bean
的名称,首先会用 @Component
的 value
属性,若是为空或空字符串则默认使用类名,并把首字母转成小写;而后对一些注解的解析,如 @Lazy
、@Primary
、@DependsOn
等;最后检查注册中心中是否包含当前 beanName
,若是没有直接添加进注册中心,不然若是不是同一个类会抛出异常。好比 com.leisurexi.a.User
和 com.leisurexi.b.User
同时添加 @Component
注解而且不手动指定不一样的 beanName
在启动时就会抛出异常。@Configuration
注解的 ConfigurationClassPostProcessor
。@Autowired
、@Value
、@Inject
注解的 AutowiredAnnotationBeanPostProcessor
。@Resource
、@PostConstructor
、@PostDestroy
注解的 CommonAnnotationBeanPostProcessor
。PersistenceAnnotationBeanPostProcessor
。@EventListener
注解的 EventListenerMethodProcessor
。最后,我模仿 Spring 写了一个精简版,代码会持续更新。地址:https://github.com/leisurexi/tiny-spring。访问新博客地址,观看效果更佳 https://leisurexi.github.io/spring