掘金 后端 ( ) • 2024-04-16 10:38
  • spring中的扫描流程

spring扫描流程.png

  • spring扫描流程源码解析

    • spring在容器启动时调用invokeBeanFactoryPostProcessors方法完成了spring的扫描;主要调用 ConfigurationClassPostProcessor类完成扫描和full类型配置类通过cglib转换成代理类。先执行postProcessBeanDefinitionRegistry方法完成了配置类的扫描,在调用postProcessBeanFactory方法完成配置类的代理类的转换
    • 在processConfigBeanDefinitions方法中完成配置类BeanDefintion的标识(full或lite类型)

      • 1.遍历BeanFactory的BeanDefinitionMap,调用 ConfigurationClassUtils.checkConfigurationClassCandidate方法标志配置类类型(会过滤spring内置的BeanDefition)
      • 2.配置类按@Order的顺序进行排序,获取当前容器中(单例池中的BeanNameGenerator名称生成器)
      • 3.创建ConfigurationClassParser配置类解析器,并在构造方法中生成ComponentScanAnnotationParser注解扫描器(是用来解析@ComponentScan注解)
    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
       List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
       String[] candidateNames = registry.getBeanDefinitionNames();
       //遍历beanFactory中的beanDefinitionMap-主要是spring内置的和api手动注册的BeanDefinition
       for (String beanName : candidateNames) {
    
          BeanDefinition beanDef = registry.getBeanDefinition(beanName);
    
          //判断当前BeanDefinition是个全配置类(被@Configuration注解修饰过)是否被解析过。
          //1.当前BeanDefinition是否是个全配置类
          //2.该全配置类BeanDefinition是否已经被处理过
          if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
             if (logger.isDebugEnabled()) {
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
             }
          }
    
          //对beanDefinition是否是个全配置类或半配置类的标志设置值(在此会过滤spring中内置的BeanDefinition)
          else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
             configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
          }
       }
    
       // Return immediately if no @Configuration classes were found
       if (configCandidates.isEmpty()) {
          return;
       }
    
       // Sort by previously determined @Order value, if applicable
       //对配置类按着@Order的顺序进行排序
       configCandidates.sort((bd1, bd2) -> {
          int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
          int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
          return Integer.compare(i1, i2);
       });
    
       // Detect any custom bean name generation strategy supplied through the enclosing application context
       SingletonBeanRegistry sbr = null;
       if (registry instanceof SingletonBeanRegistry) {
          sbr = (SingletonBeanRegistry) registry;
          if (!this.localBeanNameGeneratorSet) {
             //获取bean名称生成策略,获取容器中(单例池中是否存在BeanNameGenerator)
             BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
             //一般情况是false 除非通过api往单例池中手动添加了一个
             if (generator != null) {
                this.componentScanBeanNameGenerator = generator;
                this.importBeanNameGenerator = generator;
             }
          }
       }
    
       if (this.environment == null) {
          this.environment = new StandardEnvironment();
       }
    
       // Parse each @Configuration class
       //生成ConfigurationClassParser 配置类扫描器(用于解析配置类的),构造方法会生成ComponentScanAnnotationParser注解扫描器(是用来解析@ComponentScan注解)
       ConfigurationClassParser parser = new ConfigurationClassParser(
             this.metadataReaderFactory, this.problemReporter, this.environment,
             this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    
    
       //遍历合格的配置类BeanDefinition---configCandidates
       Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
       Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
       do {
          StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
          parser.parse(candidates);
          parser.validate();
    
          Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
          configClasses.removeAll(alreadyParsed);
    
          // Read the model and create bean definitions based on its content
          if (this.reader == null) {
             this.reader = new ConfigurationClassBeanDefinitionReader(
                   registry, this.sourceExtractor, this.resourceLoader, this.environment,
                   this.importBeanNameGenerator, parser.getImportRegistry());
          }
          this.reader.loadBeanDefinitions(configClasses);
          alreadyParsed.addAll(configClasses);
          processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
    
          candidates.clear();
          if (registry.getBeanDefinitionCount() > candidateNames.length) {
             String[] newCandidateNames = registry.getBeanDefinitionNames();
             Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
             Set<String> alreadyParsedClasses = new HashSet<>();
             for (ConfigurationClass configurationClass : alreadyParsed) {
                alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
             }
             for (String candidateName : newCandidateNames) {
                if (!oldCandidateNames.contains(candidateName)) {
                   BeanDefinition bd = registry.getBeanDefinition(candidateName);
                   if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                         !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                      candidates.add(new BeanDefinitionHolder(bd, candidateName));
                   }
                }
             }
             candidateNames = newCandidateNames;
          }
       }
       while (!candidates.isEmpty());
    
       // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
       if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
          sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
       }
    
       if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
          // Clear cache in externally provided MetadataReaderFactory; this is a no-op
          // for a shared cache since it'll be cleared by the ApplicationContext.
          ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
       }
    }
    
    public static boolean checkConfigurationClassCandidate(
          BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
    
       String className = beanDef.getBeanClassName();
       if (className == null || beanDef.getFactoryMethodName() != null) {
          return false;
       }
       //BeanDefinition中注解的元数据信息,主要通过ASM字节码获取到的
       AnnotationMetadata metadata;
       if (beanDef instanceof AnnotatedBeanDefinition &&
             className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
          // Can reuse the pre-parsed metadata from the given BeanDefinition...
          metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
       }
       else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
          // Check already loaded Class if present...
          // since we possibly can't even load the class file for this Class.
          Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
    
          //过滤spring中内置的那些BeanDefinition,因为内置的5个类(spring版本不同可能会有数量差异)都是实现了这四个接口
          if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
                BeanPostProcessor.class.isAssignableFrom(beanClass) ||
                AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
                EventListenerFactory.class.isAssignableFrom(beanClass)) {
             return false;
          }
          metadata = AnnotationMetadata.introspect(beanClass);
       }
       else {
          try {
             MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
             metadata = metadataReader.getAnnotationMetadata();
          }
          catch (IOException ex) {
             if (logger.isDebugEnabled()) {
                logger.debug("Could not find class file for introspecting configuration annotations: " +
                      className, ex);
             }
             return false;
          }
       }
    
    
       Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
    
       //判断当前类是否加了@Configuration注解,并且proxyBeanMethods为true时,则该配置类就是一个全配置类,标志成full
       if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
          beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
       }
    
       //当该类没有加@Configuration注解,但加了@Component,@ComponentScan,@Import,@ImportResource这四个注解时,就标记为半配置类lite
       //或者这5个注解都没有加,但存在被@Bean修饰的方法,也是个半配置类
       else if (config != null || isConfigurationCandidate(metadata)) {
          beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
       }
       else {
          return false;
       }
    
       // It's a full or lite configuration candidate... Let's determine the order value, if any.
       Integer order = getOrder(metadata);
       //设置Order的顺序
       if (order != null) {
          beanDef.setAttribute(ORDER_ATTRIBUTE, order);
       }
    
       return true;
    }
    
    
    • ConfigurationClassParser.processConfigurationClass去解析配置类
      • 1.判断当前配置类是否已经完成解析,未解析循环调用doProcessConfigurationClass
      • 2.判断当前配置类是否加了@ComponentScans或@ComponentScan标签,调用ComponentScanAnnotationParser解析器遍历解析ComponentScan注解信息
      • 3.将扫描出来的BeanDefition集合进行配置类类型标识(full or lite)
    protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
       if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
          return;
       }
    
       //一个配置类如果被解析完成了,就会放入configurationClasses这个缓存当中
       ConfigurationClass existingClass = this.configurationClasses.get(configClass);
       if (existingClass != null) {
          if (configClass.isImported()) {
             if (existingClass.isImported()) {
                existingClass.mergeImportedBy(configClass);
             }
             // Otherwise ignore new imported config class; existing non-imported class overrides it.
             return;
          }
          else {
             // Explicit bean definition found, probably replacing an import.
             // Let's remove the old one and go with the new one.
             this.configurationClasses.remove(configClass);
             this.knownSuperclasses.values().removeIf(configClass::equals);
          }
       }
    
       // Recursively process the configuration class and its superclass hierarchy.
       SourceClass sourceClass = asSourceClass(configClass, filter);
       do {
    
          //循环调用,解析配置类
          sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
       }
       while (sourceClass != null);
    
       this.configurationClasses.put(configClass, configClass);
    }
    
    /**
     * Apply processing and build a complete {@link ConfigurationClass} by reading the
     * annotations, members and methods from the source class. This method can be called
     * multiple times as relevant sources are discovered.
     * @param configClass the configuration class being build
     * @param sourceClass a source class
     * @return the superclass, or {@code null} if none found or previously processed
     */
    @Nullable
    protected final SourceClass doProcessConfigurationClass(
          ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
          throws IOException {
    
       if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
          // Recursively process any member (nested) classes first
          //判断是否加@Component注解,加了就去处理内部类
          processMemberClasses(configClass, sourceClass, filter);
       }
    
       // Process any @PropertySource annotations
       //处理PropertySources注解信息
       for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
             sourceClass.getMetadata(), PropertySources.class,
             org.springframework.context.annotation.PropertySource.class)) {
          if (this.environment instanceof ConfigurableEnvironment) {
             processPropertySource(propertySource);
          }
          else {
             logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                   "]. Reason: Environment must implement ConfigurableEnvironment");
          }
       }
    
       // Process any @ComponentScan annotations
       Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
             sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
       if (!componentScans.isEmpty() &&
             !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
    
          //遍历ComponentScans,ComponentScan中需要扫描的包路径,basePackages是个数组
          for (AnnotationAttributes componentScan : componentScans) {
             // The config class is annotated with @ComponentScan -> perform the scan immediately
    
             //采用ConfigurationClassParser构造方法中实例化的ComponentScanAnnotationParser组件解析@ComponentScans,@ComponentScan注解
             Set<BeanDefinitionHolder> scannedBeanDefinitions =
                   this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
             // Check the set of scanned definitions for any further config classes and parse recursively if needed
             for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                if (bdCand == null) {
                   bdCand = holder.getBeanDefinition();
                }
    
                //判断扫描出来的配置类是否为全配置类或者是半配置类
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
    
                   //继续解析扫描出来的配置类
                   parse(bdCand.getBeanClassName(), holder.getBeanName());
                }
             }
          }
       }
    
       // Process any @Import annotations
       processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
    
       // Process any @ImportResource annotations
       AnnotationAttributes importResource =
             AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
       if (importResource != null) {
          String[] resources = importResource.getStringArray("locations");
          Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
          for (String resource : resources) {
             String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
             configClass.addImportedResource(resolvedResource, readerClass);
          }
       }
    
       // Process individual @Bean methods
       Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
       for (MethodMetadata methodMetadata : beanMethods) {
          configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
       }
    
       // Process default methods on interfaces
       processInterfaces(configClass, sourceClass);
    
       // Process superclass, if any
       if (sourceClass.getMetadata().hasSuperClass()) {
          String superclass = sourceClass.getMetadata().getSuperClassName();
          if (superclass != null && !superclass.startsWith("java") &&
                !this.knownSuperclasses.containsKey(superclass)) {
             this.knownSuperclasses.put(superclass, configClass);
             // Superclass found, return its annotation metadata and recurse
             return sourceClass.getSuperClass();
          }
       }
    
       // No superclass -> processing is complete
       return null;
    }
    
    • 调用ComponentScanAnnotationParser解析器的parse方法解析@ComponentScan注解
      • 1.实例化扫描器ClassPathBeanDefinitionScanner,获取注解useDefaultFilters属性值,来判断是否需要采用spring默认的includeFilters列表(内置了3个TypeFilter,new AnnotationTypeFilter(Component.class),以及spring对JSR支持的两个ManagedBean,Named
      • 2.获取bean名称生成器BeanNameGenerator,优先级(注解中配置的nameGenerator > api注册提供的(单例池中存在的) > spring默认名称生成器)
      • 将@ComponentScan注解中的配置信息设置给ComponentScanAnnotationParser,然后开始调用doScan方法对配置的basePackages进行解析完成扫描
    //解析@ComponentScans,@ComponentScan注解完成spring的扫描
    public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, String declaringClass) {
    
       //实例化扫描器--是否默认的Filter(默认true)
       ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
             componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
    
       //获取bean名称生成器 优先级(注解中配置的nameGenerator > api注册提供的(单例池中存在的) > spring默认名称生成器)
       Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
       boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
       scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
             BeanUtils.instantiateClass(generatorClass));
    
       ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
       if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
          scanner.setScopedProxyMode(scopedProxyMode);
       }
       else {
          Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
          scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
       }
    
       scanner.setResourcePattern(componentScan.getString("resourcePattern"));
    
       //过滤器分两种excludeFilters,includeFilters,Filter有三种种类型ANNOTATION,ASSIGNABLE_TYPE,CUSTOM
    
       //获取注解提供的includeFilters
       for (AnnotationAttributes includeFilterAttributes : componentScan.getAnnotationArray("includeFilters")) {
          List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(includeFilterAttributes, this.environment,
                this.resourceLoader, this.registry);
          for (TypeFilter typeFilter : typeFilters) {
             scanner.addIncludeFilter(typeFilter);
          }
       }
    
       //获取注解提供的excludeFilters
       for (AnnotationAttributes excludeFilterAttributes : componentScan.getAnnotationArray("excludeFilters")) {
          List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(excludeFilterAttributes, this.environment,
             this.resourceLoader, this.registry);
          for (TypeFilter typeFilter : typeFilters) {
             scanner.addExcludeFilter(typeFilter);
          }
       }
    
       boolean lazyInit = componentScan.getBoolean("lazyInit");
       if (lazyInit) {
          scanner.getBeanDefinitionDefaults().setLazyInit(true);
       }
    
       Set<String> basePackages = new LinkedHashSet<>();
       String[] basePackagesArray = componentScan.getStringArray("basePackages");
       for (String pkg : basePackagesArray) {
          String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
                ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
          Collections.addAll(basePackages, tokenized);
       }
       for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
          basePackages.add(ClassUtils.getPackageName(clazz));
       }
       if (basePackages.isEmpty()) {
          basePackages.add(ClassUtils.getPackageName(declaringClass));
       }
    
       //添加默认的excludeFilters-表示当前类是不需要进行扫描的,所以得排除
       scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
          @Override
          protected boolean matchClassName(String className) {
             return declaringClass.equals(className);
          }
       });
    
       //开始扫描-调用ClassPathBeanDefinitionScanner的doScan方法开始进行扫描
       return scanner.doScan(StringUtils.toStringArray(basePackages));
    }
    
    • 调用ClassPathBeanDefinitionScanner的doScan方法开始对basePackages进行扫描
      • 1.调用findCandidateComponents方法中的scanCandidateComponents方法开始进行扫描
      • 2.获取basePackage下的所有类文件的Resource,主要通过io读取(并没有将Class类对象加载到jvm中)
      • 3.通过ASM字节码技术,获取类的元数据信息,调用isCandidateComponent方法进行条件过滤 先遍历执行excludeFilters列表的TypeFilter.match方法过滤被排除的类;在遍历执行iincludeFilters列表的TypeFilter.match方筛选出合格的方法
      • 将合格的类生成BeanDefition对象存到容器的BeanDefinitionMap中
    private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
       Set<BeanDefinition> candidates = new LinkedHashSet<>();
       try {
          //获取basePackage下的所有类文件Resource
          String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                resolveBasePackage(basePackage) + '/' + this.resourcePattern;
          Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
          boolean traceEnabled = logger.isTraceEnabled();
          boolean debugEnabled = logger.isDebugEnabled();
          for (Resource resource : resources) {
             if (traceEnabled) {
                logger.trace("Scanning " + resource);
             }
             try {
                //通过ASM字节码获取到类的元数据信息,为什么不是通过反射获取到class类对象信息?
                MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
    
                //过滤符合要求的bean,并生成BeanDefinition(执行Filter进行过滤,是否添加了必要的注解等)
                if (isCandidateComponent(metadataReader)) {
                   ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                   sbd.setSource(resource);
    
                   //判断是否是接口,是否是抽象类
                   if (isCandidateComponent(sbd)) {
                      if (debugEnabled) {
                         logger.debug("Identified candidate component class: " + resource);
                      }
                      //不是,则返回BeanDefinition
                      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 (FileNotFoundException ex) {
                if (traceEnabled) {
                   logger.trace("Ignored non-readable " + resource + ": " + ex.getMessage());
                }
             }
             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;
    }
    
    • TypeFilter中match方法进行筛选合格类
      • spring扩展点-matchSelf方法
      • spring扩展点-matchClassName方法
      • 是否考虑considerInherited,是的话执行matchSuperClass
      • 是否考虑considerInterfaces,是的话执行matchInterface
      • matchSelf方法,matchClassName方法,matchSuperClass,matchInterface;spring的扩展点方法,子类可以重写完成自定义的过滤规则
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
          throws IOException {
    
       // This method optimizes avoiding unnecessary creation of ClassReaders
       // as well as visiting over those readers.
       //匹配自我-spring的扩展机制-默认为false则不会进if里面
    
       //spring内置默认的AnnotationTypeFilter重写方法-调用的子类的
       if (matchSelf(metadataReader)) {
          return true;
       }
       ClassMetadata metadata = metadataReader.getClassMetadata();
    
       //是否匹配类名称-spring的扩展机制-默认为false则不会进if里面
       if (matchClassName(metadata.getClassName())) {
          return true;
       }
    
       //considerInherited,considerInterfaces默认都为false
    
       //是否考虑扫描Inherited
       if (this.considerInherited) {
          String superClassName = metadata.getSuperClassName();
          if (superClassName != null) {
             // Optimization to avoid creating ClassReader for superclass.
             Boolean superClassMatch = matchSuperClass(superClassName);
             if (superClassMatch != null) {
                if (superClassMatch.booleanValue()) {
                   return true;
                }
             }
             else {
                // Need to read superclass to determine a match...
                try {
                   if (match(metadata.getSuperClassName(), metadataReaderFactory)) {
                      return true;
                   }
                }
                catch (IOException ex) {
                   if (logger.isDebugEnabled()) {
                      logger.debug("Could not read superclass [" + metadata.getSuperClassName() +
                            "] of type-filtered class [" + metadata.getClassName() + "]");
                   }
                }
             }
          }
       }
       //是否考虑扫描Interfaces
       if (this.considerInterfaces) {
          for (String ifc : metadata.getInterfaceNames()) {
             // Optimization to avoid creating ClassReader for superclass
             //考虑接口时,匹配规则
             Boolean interfaceMatch = matchInterface(ifc);
             if (interfaceMatch != null) {
                if (interfaceMatch.booleanValue()) {
                   return true;
                }
             }
             else {
                // Need to read interface to determine a match...
                try {
                   if (match(ifc, metadataReaderFactory)) {
                      return true;
                   }
                }
                catch (IOException ex) {
                   if (logger.isDebugEnabled()) {
                      logger.debug("Could not read interface [" + ifc + "] for type-filtered class [" +
                            metadata.getClassName() + "]");
                   }
                }
             }
          }
       }
    
       return false;
    }
    
  • spring是怎么完成扫描的?

    • spring容器启动时会调用invokeBeanFactoryPostProcessors方法完成了扫描;其中是调用spring内置的ConfigurationClassBeanPostProcessor的postProcessBeanDefinitionRegistry完成了扫描
    • 首先会过滤spring内置的几个配置类的BeanDefinition后,创建ConfigurationClassParser配置类解析器去解析合格的配置类
    • 第二步判断配置类是否存在@ComponentScan注解,存在会调用ConfigurationClassParser配置类的ComponentScanAnnotationParser解析器去解析@ComponentScan注解
    • 第三步创建ClassPathBeanDefinitionScanner扫描器并将@ComponentScan注解配置信息设置给扫描器后,调用doscan方法完成basePackages的扫描
    • 第四步通过io获取到basePackages下所有的文件Resource,并通过ASM获取类的元数据信息,遍历执行excludeFilters和includeFilters列的TypeFilter的match筛选出合格的类,
    • 第5步实例化ScannedGenericBeanDefinition对象,判断是否接口是否抽象、是否加了LockUp注解等等,正常添加到列表,遍历扫描到的beanDefinition列表,标识配置类的类型(full or lite or null )后存到BeanFactory中的BeanDefinitionMap中;
  • spring扫描为何会有两个扫描器,区别是什么

    • spring会创建两个ClassPathBeanDefinitionScanner扫描器(构造方法和自动扫描创建),用户可以调用api手动完成扫描(context.scan方法)以及@Componnt注解的自动扫描
    • 手动调用可以完成动态化编程,是一定会执行的,而@Componnt注解的自动扫描是有加载时机的可能不会执行,也不能完成动态条件加载,但可以提供一些定制化的功能,过滤等功能;api手动扫描动态化编程功能比较少
  • spring扫描时为何采用ASM完成class类信息?

    • spring通过IO从磁盘上加载类文件的Resource到内存后,然后通过ASM获取类的元数据信息,并不会将类加载到jvm的元空间的中,而通过Class.forName加载类信息时,会将类对象加载jvm的元空间,会执行static代码块;这样在某些场景下出现某种错误,spring本着不打扰用户的程序的执行行为,所以采用ASM字节码去进行扫描
    • ASM字节码加载的效率是高于反射的
  • spring内置的三个TypeFilter以及一个AbstractTypeHierarchyTraversingFilter,以及TypeFilter的类型?

    • spring的默认includeFilters内置了三个TypeFilter,分别是AnnotationTypeFilter(Component.class),AnnotationTypeFilter(ManagedBean.class),AnnotationTypeFilter(Named.class)以及excludeFilters内置了一个AbstractTypeHierarchyTraversingFilter;
    • AbstractTypeHierarchyTraversingFilter重写matchClassName用来过滤排除当前配置类
    • AnnotationTypeFilter重写matchSelf方法来过滤当前是否加了该注解Named,ManagedBean是spring对JSR的支持,主要是解决在轻量型服务在不当不引入spring的依赖包,只引入轻量型的jar包,但该服务最终会被spring服务调用,所以spring支持这种可插拔式的配置;
    • spring的TypeFilter的类型有两种ANNOTATION:用于过滤被特定注解标记的候选者;ASSIGNABLE_TYPE:用于过滤可分配给特定类型的候选者。
  • spring full类型的配置类解析流程

    • spring在容器启动时调用invokeBeanFactoryPostProcessors方法完成了spring的扫描;主要调用ConfigurationClassPostProcessor的postProcessBeanFactory方法完成full类型的配置类的代理类的转换

      • 1.调用enhanceConfigurationClasses方法完成full类型的配置类的解析
      • 2.向beanFactory容器添加ImportAwareBeanPostProcessor实例对象,主要是为了对full类的配置类的bean生命周期中进行属性填充阶段时,调用postProcessProperties方法对cglib增强的full类型的配置类(实现了EnhancedConfiguration接口)进行属性填充,调用setBeanFactory方法,通过动态代理调用代理对象的增强方法,通过反射将容器中的beanFactory赋值给代理类的$$beanFactory属性
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
       int factoryId = System.identityHashCode(beanFactory);
       if (this.factoriesPostProcessed.contains(factoryId)) {
          throw new IllegalStateException(
                "postProcessBeanFactory already called on this post-processor against " + beanFactory);
       }
       this.factoriesPostProcessed.add(factoryId);
       if (!this.registriesPostProcessed.contains(factoryId)) {
          // BeanDefinitionRegistryPostProcessor hook apparently not supported...
          // Simply call processConfigurationClasses lazily at this point then.
          processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
       }
    
       //开始处理beanFactory中BeanDefinitionMap中被标记为full(全配置类的)BeanDefinition,完成增强生成代理类(未实例化),最后在bean的生命周期完成实例化
       enhanceConfigurationClasses(beanFactory);
    
       //添加ImportAwareBeanPostProcessor,主要是在完成扫描后,实例化bean时进行属性填充时
       //对全配置类(full类)时,为cglib生成的代理类设置后,将容器BeanFactory值赋值代理对象的$$BeanFactory
       beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
    }
    
    • 调用enhanceConfigurationClasses创建full类型配置类的动态代理类

      • 1.遍历容器中BeanDefinitionMap(spring已经完成扫描),获取full类型的BeanDefition
      • 2.创建ConfigurationClassEnhancer配置类增强器,调用enhance方法生成cglib代理类
      • 3.替换beanDefinition中的beanClass
    public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
       StartupStep enhanceConfigClasses = this.applicationStartup.start("spring.context.config-classes.enhance");
       Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
    
       //此时spring已经完成了扫描,所以可能存在多个配置类(扫描出来的配置累)
       for (String beanName : beanFactory.getBeanDefinitionNames()) {
          BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
    
          //获取当前BeanDefinition的配置类的类型
          Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
    
          AnnotationMetadata annotationMetadata = null;
          MethodMetadata methodMetadata = null;
    
          //判断是否添加了注解(BeanDefinition可能手动添加的,可能是非扫描出来的)
          if (beanDef instanceof AnnotatedBeanDefinition) {
             AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDef;
             annotationMetadata = annotatedBeanDefinition.getMetadata();
             methodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();
          }
          if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
             // Configuration class (full or lite) or a configuration-derived @Bean method
             // -> eagerly resolve bean class at this point, unless it's a 'lite' configuration
             // or component class without @Bean methods.
             AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
             if (!abd.hasBeanClass()) {
                boolean liteConfigurationCandidateWithoutBeanMethods =
                      (ConfigurationClassUtils.CONFIGURATION_CLASS_LITE.equals(configClassAttr) &&
                         annotationMetadata != null && !ConfigurationClassUtils.hasBeanMethods(annotationMetadata));
                if (!liteConfigurationCandidateWithoutBeanMethods) {
                   try {
                      abd.resolveBeanClass(this.beanClassLoader);
                   }
                   catch (Throwable ex) {
                      throw new IllegalStateException(
                            "Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
                   }
                }
             }
          }
    
          //是否被标记为full(全配置类)
          if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
             if (!(beanDef instanceof AbstractBeanDefinition)) {
                throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
                      beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
             }
             else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
                logger.info("Cannot enhance @Configuration bean definition '" + beanName +
                      "' since its singleton instance has been created too early. The typical cause " +
                      "is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
                      "return type: Consider declaring such methods as 'static'.");
             }
             configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
          }
       }
       if (configBeanDefs.isEmpty() || NativeDetector.inNativeImage()) {
          // nothing to enhance -> return immediately
          enhanceConfigClasses.end();
          return;
       }
    
       ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
       for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
          AbstractBeanDefinition beanDef = entry.getValue();
          // If a @Configuration class gets proxied, always proxy the target class
          beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
          // Set enhanced subclass of the user-specified bean class
          Class<?> configClass = beanDef.getBeanClass();
    
    
          //完成full全配置类的类增强,cglib完成生成代理类
          Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
          if (configClass != enhancedClass) {
             if (logger.isTraceEnabled()) {
                logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
                      "enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
             }
             //替换beanDefinition的BeanClass
             beanDef.setBeanClass(enhancedClass);
          }
       }
       enhanceConfigClasses.tag("classCount", () -> String.valueOf(configBeanDefs.keySet().size())).end();
    }
    
    • 通过cglib生成代理类

      • 1.判断当前类是否已经被动态代理了
      • 2.创建cglib动态代理中Enhancer增强器,配置代理类的属性,如设置父类类型,需要实现的EnhancedConfiguration接口,设置CallbackFilter,以及为代理类添加一个$$beanFactory属性字段
      • 3.当调用enhancer.createClass()就会产生代理类
    public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
       if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
          if (logger.isDebugEnabled()) {
             logger.debug(String.format("Ignoring request to enhance %s as it has " +
                   "already been enhanced. This usually indicates that more than one " +
                   "ConfigurationClassPostProcessor has been registered (e.g. via " +
                   "<context:annotation-config>). This is harmless, but you may " +
                   "want check your configuration and remove one CCPP if possible",
                   configClass.getName()));
          }
          return configClass;
       }
       //完成cglib对类的增强,创建一个继承configClass实现了EnhancedConfiguration接口的代理类
       Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
       if (logger.isTraceEnabled()) {
          logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
                configClass.getName(), enhancedClass.getName()));
       }
       return enhancedClass;
    }
    
    /**
     * Creates a new CGLIB {@link Enhancer} instance.
     */
    private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
    
       //cglib动态代理-主要是通过继承被代理类,生成子类实现cglib动态代理实现增强
       //生成增强器
       Enhancer enhancer = new Enhancer();
    
       //将配置类设置成代理类的父类
       enhancer.setSuperclass(configSuperClass);
    
       //设置代理类需要实现的接口,EnhancedConfiguration extends BeanFactoryAware 主要是完成bean作用域的完整性
       enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
    
    
    
       enhancer.setUseFactory(false);
       //spring cglib中生成代理类的命名规则
       enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    
       //为代理类添加一个$$beanFactory属性字段,BeanFactoryAwareGeneratorStrategy是对CGLIB的DefaultGeneratorStrategy的扩展
       enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
    
       //设置代理增强Filter,为某个方法的执行完成不同行为的增强
       //CallbackFilter会对方法进行过滤,调用accept()方法来实现对不同的方法,完成不同的行为增强
       enhancer.setCallbackFilter(CALLBACK_FILTER);
    
       //enhancer.setCallbacks();  setCallbacks必须要和setCallbackFilter两个搭配使用,完成对不同的方法实现不同的行为增强
       //enhancer.setCallback(); setCallback默认会对所有方法进行增强
    
       enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
       return enhancer;
    }
    
    • 设置Enhancer的CallbackFilter为ConditionalCallbackFilter

      • 1.spring通过ConditionalCallbackFilter完成了对不同方法的调用,实现了不同方法行为的增强(spring主要对加了@Bean注解的方法,以及setFactory方法进行增强),主要是通过accept方法,返回不同的Callback然后执行intercept方法实现增强。
      • @Bean注解的方法采用的是BeanMethodInterceptor的类型Callback进行增强
      • setFactory方法采用的是BeanFactoryAwareMethodInterceptor的类型Callback进行增强
    private static class ConditionalCallbackFilter implements CallbackFilter {
    
    
       //new BeanMethodInterceptor(),
       //new BeanFactoryAwareMethodInterceptor(),
       //NoOp.INSTANCE
       //设置了3种Callback的增强,BeanMethodInterceptor用于增强@bean修饰的方法,BeanFactoryAwareMethodInterceptor用于增强setBeanFactory方法
       private final Callback[] callbacks;
    
       private final Class<?>[] callbackTypes;
    
       public ConditionalCallbackFilter(Callback[] callbacks) {
          this.callbacks = callbacks;
          this.callbackTypes = new Class<?>[callbacks.length];
          for (int i = 0; i < callbacks.length; i++) {
             this.callbackTypes[i] = callbacks[i].getClass();
          }
       }
    
    
       //对不同行为方法,返回不同的callback去完成方法的增强
       //返回匹配上数组的索引下标,完成cglib对方法的增强
    
       //cglib可以传入多个callbacks增强,但使用时会调用accept来确认使用哪一个去进行行为方法的增强
       @Override
       public int accept(Method method) {
          for (int i = 0; i < this.callbacks.length; i++) {
             Callback callback = this.callbacks[i];
             //采用哪个Interceptor去进行增强委托给将callback.isMatch去过滤(完成控制反转),实现了接口单一原则
    
             //判断代理类增强的方法是否为setBeanFactory方法,是的话则使用BeanFactoryAwareMethodInterceptor
             //判断代理类增强的方法加了@Bean注解且方法名称 不为setBeanFactory是的话则使用BeanMethodInterceptor
             //全部是则使用NoOp.INSTANCE去进行增强(什么都不做,即不进行增强)
             if (!(callback instanceof ConditionalCallback) || ((ConditionalCallback) callback).isMatch(method)) {
                return i;
             }
          }
          throw new IllegalStateException("No callback available for method " + method.getName());
       }
    
       public Class<?>[] getCallbackTypes() {
          return this.callbackTypes;
       }
    }
    
  • spring是如何处理full类型的配置类?

  • mybatis整合spring是如何完成Mapper的扫描的,整合springboot是如何完成扫描的

  • 什么是full,lite类型的配置类,二者有什么区别?

    • full类型的配置类是一个被cglib增强-转换成动态代理的类,并保证了了@bean产生的bean对象的作用域的完整性,而lite类型的配置类不会被cglib增强代理且不能保证bean对象的作用域的完整性
  • 怎么查看cglib动态生成的类

public static void saveGeneratedCGlibProxyFiles(String dir) throws Exception {

Field field = System.class.getDeclaredField("props");

field.setAccessible(true);

Properties props = (Properties) field.get(null);

System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, dir);//dir为

保存文件路径

props.put("net.sf.cglib.core.DebuggingClassWriter.traceEnabled", "true");

}