-
spring中的扫描流程
-
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");
}