这一次搞懂Spring自定义标签以及注解解析原理( 二 )
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 {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 void parseTypeFilters(Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext) {// Parse exclude and include filter elements.ClassLoader classLoader = scanner.getResourceLoader().getClassLoader();// 将component-scan的子标签include-filter和exclude-filter添加到scanner中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 {if (INCLUDE_FILTER_ELEMENT.equals(localName)) {TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);scanner.addIncludeFilter(typeFilter);}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());}}} }【这一次搞懂Spring自定义标签以及注解解析原理】上面不重要的方法我已经删掉了 , 首先获取use-default-filters属性 , 传入到ClassPathBeanDefinitionScanner构造器中判断是否使用默认的过滤器 , 如果是就调用registerDefaultFilters方法将@Component注解过滤器添加到includeFilters属性中;创建后紧接着调用了parseTypeFilters方法去解析include-filter和exclude-filter子标签 , 并分别添加到includeFilters和excludeFilters标签中(关于这两个标签的作用这里不再赘述) , 所以这一步就是创建包含过滤器的class扫描器 , 接着就可以调用scan方法完成扫描注册了(如果我们要自定义注解是不是也可以这样实现呢?) 。
protected Set doScan(String... basePackages) {Assert.notEmpty(basePackages, "At least one base package must be specified");Set beanDefinitions = new LinkedHashSet<>();for (String basePackage : basePackages) {// 这里就是实际扫描符合条件的类并封装为ScannedGenericBeanDefinition对象Set candidates = findCandidateComponents(basePackage);// 接着在每个单独解析未解析的信息并注册到缓存中for (BeanDefinition candidate : candidates) {ScopeMetadata scopeMetadata = http://kandian.youth.cn/index/this.scopeMetadataResolver.resolveScopeMetadata(candidate);candidate.setScope(scopeMetadata.getScopeName());String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);if (candidate instanceof AbstractBeanDefinition) {postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);}// 解析@Lazy、@Primary、@DependsOn等注解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);registerBeanDefinition(definitionHolder, this.registry);}}}return beanDefinitions; } public Set findCandidateComponents(String basePackage) {if (this.componentsIndex != null}else {// 主要看这 , 扫描所有符合条件的class文件并封装为ScannedGenericBeanDefinitionreturn scanCandidateComponents(basePackage);} } private Set scanCandidateComponents(String basePackage) {Set candidates = new LinkedHashSet<>();try {String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +resolveBasePackage(basePackage) + '/' + this.resourcePattern;// 获取class文件并加载为ResourceResource[] 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 {// 获取SimpleMetadataReader对象 , 该对象持有AnnotationMetadataReadingVisitor对象MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);if (isCandidateComponent(metadataReader)) {// 将AnnotationMetadataReadingVisitor对象设置到ScannedGenericBeanDefinition中ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);sbd.setResource(resource);sbd.setSource(resource);if (isCandidateComponent(sbd)) {if (debugEnabled) {logger.debug("Identified candidate component class: " + resource);}candidates.add(sbd);}}}}}}return candidates; }
- Spring security CSRF 跨域访问限制问题
- 现在入手苹果11值吗,它跟12相比到底好在哪?看完算搞懂了
- Spring Boot搭建的一个在线文件预览系统
- 面试官:问你一个,Spring事务是如何传播的?
- 对Spring MVC接口进行Mock测试
- Spring Cloud Alibaba之 Sentinel
- SpringBoot+MyBatis+MySQL读写分离实现
- SpringBoot构造流程源码分析:Web应用类型推断
- 搭建私有Sentry日志收集系统并集成到springboot
- 让你彻底搞懂布隆过滤器!实现一个自己的BloomFilter