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注解)
scss
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();
}
}
kotlin
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)
kotlin
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进行解析完成扫描
typescript
//解析@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中
scss
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的扩展点方法,子类可以重写完成自定义的过滤规则
kotlin
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属性**;
scss
@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
scss
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()就会产生代理类
less
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进行增强**
java
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动态生成的类
java
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");
}