上篇文章中遗留了三个重要方法
1.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
2.ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
3.DefaultListableBeanFactory.getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit)
1.getBeanNamesForType()完成了beanDefinition的查找
//记一下传过来的参数值 xxx.class true false
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
/**
* 三个判断条件
* 1. !isConfigurationFrozen()返回beanFactory的configurationFrozen属性默认为false
* private volatile boolean configurationFrozen = false;
* 2. 传递过来type是否为null
* 3. 传递过来的allowEagerInit是否为false
*/
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
//因为第一个条件默认为true所以一定会执行
return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
}
Map<Class<?>, String[]> cache =
(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
String[] resolvedBeanNames = cache.get(type);
if (resolvedBeanNames != null) {
return resolvedBeanNames;
}
resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
cache.put(type, resolvedBeanNames);
}
return resolvedBeanNames;
}
//单纯的new了一个对象封装了type类型
public static ResolvableType forRawClass(@Nullable Class<?> clazz) {
return new ResolvableType(clazz) {
@Override
public ResolvableType[] getGenerics() {
return EMPTY_TYPES_ARRAY;
}
@Override
public boolean isAssignableFrom(Class<?> other) {
return (clazz == null || ClassUtils.isAssignable(clazz, other));
}
@Override
public boolean isAssignableFrom(ResolvableType other) {
Class<?> otherClass = other.getRawClass();
return (otherClass != null && (clazz == null || ClassUtils.isAssignable(clazz, otherClass)));
}
};
}
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
//创建一个List集合封装匹配当前类型的beanName集合
List<String> result = new ArrayList<>();
//循环此时beanDefinitionNames中的所有key拿到全限定类名
for (String beanName : this.beanDefinitionNames) {
//先判断本次循环的beanName是否存在于aliasMap
//return this.aliasMap.containsKey(name);
if (!isAlias(beanName)) {
try {
/**
* RootBeanDefinition:通常用在bean的实例化阶段,为了方便实例化操作,提供了大量的缓存字段,方便重复实例化时减少工作量。
* 他会先尝试从mergedBeanDefinitions中拿到key为beanName的beanDefinition
* mergedBeanDefinitions:存放合成的beanDefinition,至于合成怎么理解,通过xml的方式指定了bean的父bean <bean parent="xxx"></bean>
* 找不到的话就会从beanDefinitionMap中找,然后返回beanDefinition
*/
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
/** 三个大判断
* 1.private boolean abstractFlag = false;默认为true
* 2.只要有一个为true即可,mbd.hasBeanClass()一定为true
* 3.!containsSingleton(factoryBeanName)默认为false,最终为true
*/
if (!mbd.isAbstract() && (allowEagerInit ||
((mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading())) &&
!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
// 判断是否是一个FactoryBean,最简单的理解就是是否实现了FactoryBean这个接口
boolean isFactoryBean = isFactoryBean(beanName, mbd);
//默认为null
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
/**
* 这么复杂的判断,可以看到他是3个&&符号,而每一个又嵌套了||符号,
* 直接看重点 isTypeMatch(beanName, type);
* type封装了需要查找的beanDefinition的类型
* 这个方法没什么意思有兴趣的同学自己看,不建议看!就是通过beanName找到beanDefinition判断是否和指定类型匹配
*/
boolean matchFound =
(allowEagerInit || !isFactoryBean ||
(dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) &&
(includeNonSingletons ||
(dbd != null ? mbd.isSingleton() : isSingleton(beanName))) &&
isTypeMatch(beanName, type);
//如果是一个FactoryBean,就在他的beanName的前面加上一个‘&’
if (!matchFound && isFactoryBean) {
beanName = FACTORY_BEAN_PREFIX + beanName;
//重新判断matchFound
matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);
}
//如果类型匹配就把beanName添加进result集合
if (matchFound) {
result.add(beanName);
}
}
} catch (CannotLoadBeanClassException ex) {
if (allowEagerInit) {
throw ex;
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex);
}
onSuppressedException(ex);
} catch (BeanDefinitionStoreException ex) {
if (allowEagerInit) {
throw ex;
}
// Probably contains a placeholder: let's ignore it for type matching purposes.
if (this.logger.isDebugEnabled()) {
this.logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);
}
onSuppressedException(ex);
}
}
}
//循环manualSingletonNames集合,beanFactory的初始化过程中添加了3个beanName
for (String beanName : this.manualSingletonNames) {
try {
// 判断是否为FactoryBean,默认都不是
if (isFactoryBean(beanName)) {
if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
result.add(beanName);
continue;
}
beanName = FACTORY_BEAN_PREFIX + beanName;
}
//判断是否原始bean实例,有兴趣的自己看,默认都不是
if (isTypeMatch(beanName, type)) {
result.add(beanName);
}
} catch (NoSuchBeanDefinitionException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to check manually registered singleton with name '" + beanName + "'", ex);
}
}
}
//
return StringUtils.toStringArray(result);
}
2.postProcessBeanDefinitionRegistry()太重要了,一句话没法总结
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
/**
* 根据内存地址,生成唯一标识 ,用来验证重复处理
* 每次创建Context都会产生一个新的registryId,
* 只要不重新创建,返回的值都是同一个
* 也就是说当前方法只会执行一次
*/
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
//解析配置类
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
//创建List集合封装所有注解类的beanDefinition
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//String集合保存了所有beanDefinition的beanName
String[] candidateNames = registry.getBeanDefinitionNames();
/**
* 循环所有candidateNames
*/
for (String beanName : candidateNames) {
//根据beanName从beanDefinitionMap中拿到beanDefinition
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//判断当前的 beanDefinition 是不是一个配置类
// FullConfiguration 全配置类
// LiteConfiguration 半配置类
// 至于这两种配置类有什么区别有什么用,下文中都会详解
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
// 如果他是一个配置类那么就会打印语句 该beanDefinition已经是一个配置类
//正常情况下他是不会走的,因为现在spring并不知道谁是配置类 都是beanDefinition
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
//该方法就是判断那个是配置类,并且判断到底是全配置类、半配置类、不是配置类
//所有的beanDefinition都会进行判断,如果是配置类则创建BeanDefinitionHolder来封装beanDefinition
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
//看spring是如何判断类是否是配置类
public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
//拿到类的全限定类名
String className = beanDef.getBeanClassName();
//如果className为空直接返回
if (className == null || beanDef.getFactoryMethodName() != null) {
return false;
}
//封装类的元数据(所有注解)
AnnotationMetadata metadata;
/**
* 先判断该beanDefinition是否实现了AnnotatedBeanDefinition
* spring中的RootBeanDefinition代表spring内置的类
* AnnotatedBeanDefinition代表通过reader读取进来的
* ScannerBeanDefinition代表通过Scanner扫描进来的
* 如果第一个判断满足,则当前的beanDefinition强转成AnnotatedBeanDefinition,比较他的ClassName是否一致,有可能会出现FactoryBean这种情况,正常情况下都一致
*/
if (beanDef instanceof AnnotatedBeanDefinition &&
className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
//拿到配置类上的所有注解信息
metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
//所有beanDefinition都实现了AbstractBeanDefinition,再判断是否有beanClass
} else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
//拿到所有注解信息
Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
metadata = new StandardAnnotationMetadata(beanClass, true);
} 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;
}
}
/**
* 判断他是不是一个全配置类
* 很简单 直接判断她有没有 @Configuration 这个注解 如果有就给当前beanDefinition添加一个key-value用来表示是全配置类
*/
if (isFullConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
/**
* 判断是不是半配置类,如果当前配置类有下面这四个注解中的一个或者有加了@bean的方法则证明是半配置类
* @Component.class.
* @omponentScan.class.
* @Import.class.
* @ImportResource.class.
* 同样添加一个key-value
*/
else if (isLiteConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
//如果都不满足,直接返回false
else {
return false;
}
//判断是否有@Order注解,如果有多个配置类则会根据@Order注解来决定执行顺序
Integer order = getOrder(metadata);
if (order != null) {
//同样添加一个key-value
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
return true;
}
/**
* 如果没有注解类,直接返回
*/
if (configCandidates.isEmpty()) {
return;
}
/**
* 如果有多个配置类,并且都实现了Order接口,则按升序排序
* 有兴趣自己去看
*/
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
});
/**
* 拿到beanFactory然后getSingleton()就是从单例池拿是否有自定义的实现了internalConfigurationBeanNameGenerator接口的类
* 如果不为空则更改componentScan和importBean的解析方式,
* 如果为空默认使用spring自己的解析器
*/
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
//ConfigurationClassPostProcessor的environment如果为null则new StandardEnvironment()
//不可能为null,因为手动注册进beanDefinitionMap的时候给他设置了Context的enviroment
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
/**
* 初始化一个ConfigurationClassParser用来解析配置类,把ConfigurationClassPostProcessor的部分属性添加给他
*/
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 对扫描出来的配置类进行去重操作
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
// 创建一个set集合来缓存已经解析完成的配置类
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
/**
* 循环解析,还是因为配置类解析完成后回把扫描到的类转变成beanDefiniton添加进beanDefinitionMap中
* 防止这些beanDefinition还是配置类
*/
do {
//解析所有配置类
parser.parse(candidates);
public void parse(Set<BeanDefinitionHolder> configCandidates) {
//省略的代码不重要,直接看重点
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
//判断是否需要解析,@ConditionOnBean注解 springboot大量使用
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
//判断同一个配置类是否重复加载过
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
//如果重复加载过,则合并
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
return;
} else {
// 从集合中移除旧的配置类,后续逻辑将处理新的配置类
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
//单纯进行了数据转换 多了一些属性,底层依然还是appConfig配置类
SourceClass sourceClass = asSourceClass(configClass);
do {
//真正解析一个类
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
//返回的值不为空,表示解析的配置类还有父配置类,继续解析
while (sourceClass != null);
//添加到到一个临时map中
this.configurationClasses.put(configClass, configClass);
}
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
//递归处理内部类99%的情况不会写内部类
processMemberClasses(configClass, sourceClass);
/**
* 拿到配置类上的@PropertySources注解
* @PropertySources注解是吧properties配置文件中的值存储到Spring的Environment中,
* Environment接口提供方法去读取配置文件中的值,参数是properties文件中定义的key值。
* 有兴趣的同学自己看
*/
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
} else {
logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
/**
* 拿到配置类上的@ComponentScan注解中的信息,封装成AnnotationAttributes对象保存进集合中
* 并且设置一些默认属性
* 为什么用集合因为 ComponentScan[] value()
*/
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
//如果不为空并且不跳过就对@ComponentScan进行解析
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
// 循环处理componentScans
for (AnnotationAttributes componentScan : componentScans) {
/**
* 对包路径下的类进行解析,然后变成beanDefinition注入beanDefinitionMap中
* scannedBeanDefinitions保存了所有成功注入的类的BeanDefinitionHolder
*/
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
//创建一个扫描器,扫描包转换成beanDefinition
//这也证明了在构造方法中的那个扫描器只是用来通过api扫描的
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
。。。。。。。
//中间的方法有兴趣自己去看,主要就是对ComponentScan的其他属性进行解析和添加过滤器
。。。。。。。
//创建set集合保存包路径
Set<String> basePackages = new LinkedHashSet<>();
//拿到@ComponentScan注解上的basePackages属性的值
String[] basePackagesArray = componentScan.getStringArray("basePackages");
//主要就是对包路径进行解析校验操作,比如说去掉空格、解析转义符等等
for (String pkg : basePackagesArray) {
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
basePackages.addAll(Arrays.asList(tokenized));
}
//调用扫描器执行扫描包路径操作
return scanner.doScan(StringUtils.toStringArray(basePackages));
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
//检验basePackages是否为空
Assert.notEmpty(basePackages, "At least one base package must be specified");
//保存扫描出来的所有类的beanDefinition
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
//根据basePackage加载路径下所有java文件,并扫描出所有bean组件,并且转换成beanDefinition
//简单分析一下如何扫描出来的
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
//对路径进行解析: "classpath:xxx/xxx/**/*.class"
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
//拿到路径下的所有class文件,使用了asm技术,有兴趣的同学可以自己去了解
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
//对每个文件进行循环判断
for (Resource resource : resources) {
//默认为true
if (resource.isReadable()) {
try {
//拿到每个class文件上的注解
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
//对注解进行解析有没有@Componet注解,避免不必要的类被创建
if (isCandidateComponent(metadataReader)) {
//创建了ScannedGenericBeanDefinition 类型的bd
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
//把绝对路径设置给beanDefinition
sbd.setResource(resource);
sbd.setSource(resource);
//接口、抽象类、有@Lookup注解都不会被创建
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
//存到set集合中去
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 (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to read candidate component class: " + resource, ex);
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because not readable: " + resource);
}
}
}
}
//最后把扫描出来的所有beanDefinition集合返回
return candidates;
}
//遍历扫描出来的beanDefinition
for (BeanDefinition candidate : candidates) {
//解析作用域Scope
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
//利用beanNameGenerator生成beanName,类名首字母小写
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
/**
* 一定会执行,因为ScannedGenericBeanDefinition是 AbstractBeanDefinition的子类
* 此时他的注解信息全都是默认的
* 但是配置类可以对扫描出来的bd进行默认注解设置
* 此时就对bd进行默认修改
*/
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
/**
* 此时beanDefinition自己的注解信息放在beanDefinition中的metadata中
* 从metadata中解析到beanDefinition结构中,主要是处理Lazy, primary DependsOn, Role ,Description这五个注解
*/
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
//检查当前bean是否已经注册,不存在则注册
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
/**
* 把beanDefinition注册到beanDefinitionMap集合中,并没有直接放到singeltonObjects中
*/
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
// 遍历扫描出的bean定义是否是配置类bean
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
/**
* 如果扫描出的bean定义是配置类(全配置类或者半配置类),则继续调用parse方法,
* 也就说大部分都会在去执行一遍,因为都加了@component/@service...等注解
* 内部再次调用doProcessConfigurationClas(),递归解析
*/
if (ConfigurationClassUtils.checkConfigurationClassCandidate(
holder.getBeanDefinition(), this.metadataReaderFactory)) {
parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
}
}
}
}
/**
* 上面的代码完成对@ComponentScan注解的解析,而且解析出来直接注册进beanDefinitionMap中
*/
spring提供的两个扩展接口
importSelector
importBeanDefinitionRegister
/**
* 注意如果你是通过@componentScan的方式扫描注入的实现了importSelector和importBeanDefinitionRegister
* 全部都是一个普通的bean,也就是说不会去执行实现的方法
* 处理@import的三种情况
* 1. importSelector 执行方法,结果保存在deferredImportSelectors集合中
* 2. 普通类 把所有类保存在imports集合中
* 3. importBeanDefinitionRegister 不执行方法,保存在importBeanDefinitionRegistrars集合中
* getImports(sourceClass) 拿到当前类上的@import注解值,也会查找子注解上的所有@import注解
* 该方法仅仅只是把类扫描出来保存在集合中,并没有转换成beanDefinition
*/
processImports(configClass, sourceClass, getImports(sourceClass), true);
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) throws IOException {
//如果没有import注解直接返回
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
} else {
//
this.importStack.push(configClass);
try {
//循环解析所有@impor
for (SourceClass candidate : importCandidates) {
//判断当前这个类是否实现了 ImportSelector 接口
if (candidate.isAssignable(ImportSelector.class)) {
//利用反射,返回该类唯一Class实例对象
Class<?> candidateClass = candidate.loadClass();
//利用class实例通过构造方法反射得到对象
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
//如果该类实现了spring中的Aware接口,则添加到一个集合中后续执行
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
//如果他实现的是 DeferredImportSelector接口 则添加到一个List集合 以后进行执行
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
this.deferredImportSelectors.add(
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
} else {
//执行selector.selectImports()方法拿到真正需要被注入的类的全限定名放入数组中
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
//类型转换 数组--->集合
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
/**
* 递归解析集合中的所有类
* 如果 importSourceClasses 中为空直接返回,否则解析 selector.selectImports() 中的类
*/
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
//判断该类是否实现了 ImportBeanDefinitionRegistrar 接口
} else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
//此时并没有执行他的registerBeanDefinitions方法,仅仅只是把当前类保存到集合中
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
//如果它是一个普通类
} else {
//注册到imports集合中,此时并没有转换成beanDefinition
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass));
}
}
} catch (BeanDefinitionStoreException ex) {
throw ex;
} catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
} finally {
this.importStack.pop();
}
}
}
//拿到所有@ImportResource注解,有兴趣自己看
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);
}
}
//拿到该类中的所有加了@bean注解的方法,直接通过元数据信息就可以拿到
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
//将解析出的所有@Bean注解方法添加到beanMethods集合中,也仅仅只是保存没有转换成beanDefinition
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
/**
* 处理配置类的接口中(也就是当前正在解析的类)所有添加@Bean注解的方法,
* 内部通过遍历所有接口,解析得到@Bean注解方法,并添加到configClass配置类信息中
*/
processInterfaces(configClass, sourceClass);
// 如果有父类,则返回父类,一定会执行,因为所有类都有父类(Object)
if (sourceClass.getMetadata().hasSuperClass()) {
//拿到它的父类
String superclass = sourceClass.getMetadata().getSuperClassName();
//简单理解,如果他的父类还是配置类则递归解析父类
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
return sourceClass.getSuperClass();
}
}
//如果是非配置类直接返回null
return null;
}
- 不容易,终于绕回来了,如果你还知道下面的代码是在那个方法中,证明你有天赋!
//主要校验扫描出来的有@Component类是否有final修饰符(CGLIB代理是生成一个子类,因此原先的类不能使用final修饰)
parser.validate();
//存放所有扫描出来有@component注解的类
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
//移除掉已经解析过的配置类
configClasses.removeAll(alreadyParsed);
//如果读取器为空则创建一个单例模式--懒汉式,用来把对象转换为bd
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
/**
* 这里值得注意的是扫描出来的bean当中可能包含了特殊类
* 比如importBeanDefinitionRegister 也会在这个方法中处理
* configClasses主要包含的是import的普通类、importSector中方法返回的普通类、@bean方法、@importResources
* 每个集合对应什么,上文中都说明了
*/
this.reader.loadBeanDefinitions(configClasses);
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass,
TrackedConditionEvaluator trackedConditionEvaluator) {
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
//通过@import注入的类注册为beanDefinition 放入map集合中
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//将@Bean方法注册为beanDefinition 放入map集合中
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
//将configClass中通过ImportResource指定的资源注册为bean
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
//执行configClass中实现ImportedBeanDefinitionRegistrar接口的方法,然后把该类注册进beanDefinitionMap中
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
//将已经执行过的配置类添加进执行完毕的集合中
alreadyParsed.addAll(configClasses);
//清空candidates集合,表示已经全部解析完毕
candidates.clear();
//再次获取容器中bean定义数量 如果大于之前获取的bean定义数量,则说明有新的bean注册到容器中,在判断一遍此时beanDefinitionMap中是否有没执行的配置类
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);
//新注册的bean如果也是@Configuration配置类,则添加到数据,等待解析
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
//全部解析完成则跳出循环
while (!candidates.isEmpty());
//将ImportRegistry注册为bean以支持importware@Configuration类
if (sbr != null) {
if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
}
//在外部提供的MetadataReaderFactory中清除缓存;这是不可操作的
//因为它将被ApplicationContext清除。
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
OK,这个方法我觉得完全讲透了,最后贴一下自己的测试类
只有通过@import的方式才会执行方法,不然仅仅只是一个普通类,这是spring提供的扩展点之一。@EnableXxxx 这种注解都是利用了这种特性
3.postProcessBeanFactory()最后一个方法,对配置类进行增强
//直接看重点,至于怎么进来的上篇文章中进行了解析
ConfigurationClassPostProcessor.postProcessBeanFactory();
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//生成唯一id防止重复执行
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)) {
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
//进行cglib代理
enhanceConfigurationClasses(beanFactory)
//为beanFactory添加了第三个后置处理器
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
//创建Map保存需要进行CGLIB代理的beanDefinition
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
//拿到此时beanDefinitionNames中所有的beanName
for (String beanName : beanFactory.getBeanDefinitionNames()) {
//通过key拿到map中的beanDefinition
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
//判断它是否是全配置类,在解析的过程中给配置类设置了 CONFIGURATION_CLASS_ATTRIBUTE = full
//spring中全配置类和半配置类的区别就在于是否会进行cglib代理
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
//他是否是一个基本的beanDefinition
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
//beanFactory中的singletonObjects是否存在该bean
} else if (logger.isWarnEnabled() && beanFactory.containsSingleton(beanName)) {
logger.warn("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'.");
}
//添加进需要进行cglib代理的集合中
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
//如果是空直接返回去
if (configBeanDefs.isEmpty()) {
return;
}
//创建一个cglib生成器
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
//拿到每一个beanDefinition
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
//设置属性 PRESERVE_TARGET_CLASS_ATTRIBUTE = true表示进行过cglib
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
try {
//通过反射得到本次循环中的beanDefinition对应类的Class实例
Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
if (configClass != null) {
/**
* 进行cglib动态代理,返回一个CGLIB的实例
* 为什么要进行CGLIB代理?
* 在bean的实例化过程中,会通过配置类中的@bean方法进行创建
* 但是如果@bean方法中引用了配置类中的其他@bean方法,就会创建无用对象,而且违背了spring的设立理念
* spring为了解决这种问题,就想到了通过代理对类进行增强,多进行一次判断
*/
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
//如果该类的父接口是EnhancedConfiguration.class代表已经进行过cglib代理
if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
return configClass;
}
//通过cglib生成器创建Class对象,重点就是分析CGLIB做了什么增强
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
return enhancedClass;
}
private Enhancer newEnhancer(Class<?> superclass, @Nullable ClassLoader classLoader) {
//创建一个默认的增强器
Enhancer enhancer = new Enhancer();
//设置父类为就是原始的类
enhancer.setSuperclass(superclass);
//设置实现的接口EnhancedConfiguration.class并且EnhancedConfiguration接口实现了BeanFactoryAware接口
//所以该代理类有一个实现方法setBeanFactory()
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
//设置useFactory属性为false
enhancer.setUseFactory(false);
//设置代理类的名字后缀为BySpringCGLIB
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
/**
* 添加了一个生成策略,就是为我们代理的类添加了一个属性 BeanFactory $$BeanFactory = null
* 因为代理类有一个setBeanFactory()方法,所以这个属性一定会赋值
* 好处就是我们不用添加任何一个方法,只需要通过这个属性中的方法就能拿到beanFactory做各种操作
*/
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
/**
* 添加回调过滤器,也就是对每个方法进行增强,一共添加了两个增强类
* 1.BeanMethodInterceptor(),
* 判断所有方法是否有@bean注解如果有就进行了增强
* 2.BeanFactoryAwareMethodInterceptor(),
* 判断 $$beanFactory这个属性是否有实例,有就直接返回,没有去创建
*/
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;
}
//就贴一下重点代码
private static class
BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
//首先通过反射从增强的 Configuration 注解类中获取 beanFactory
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
//beanName就是全限定类名+方法名也可以通过@bean("xxx")指定
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
/**
* 判断当前执行的方法是否是第一次执行,
*
* public xx setXX(){return new xx()};
* public xx2 setXX2(){ setXX() ; return new xx2()};
* public xx3 setXX3(){return new xx3()};
* 上面举得例子:名字是不同的 setXX setXX2
* 如果是第一次执行那么他的代理方法的名字 和 原来创建对象方法的名字是相同的
* 如果不是第一次,那么他的代理方法的名字 和 原来创建对象方法的名字是不同的
* 那么这个返回值就是 false.
*/
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
//如果是第一次。那么直接通过反射执行原方法
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}
//不是第一次,则直接从singletonObjects拿
return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}
private static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback {
@Override
@Nullable
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Field field = ReflectionUtils.findField(obj.getClass(), BEAN_FACTORY_FIELD);
Assert.state(field != null, "Unable to find generated BeanFactory field");
field.set(obj, args[0]);
//实际的(非CGLIB)超类是否实现BeanFactoryAware?
//如果是,则调用其setBeanFactory()方法。如果没有,就退出。
if (BeanFactoryAware.class.isAssignableFrom(ClassUtils.getUserClass(obj.getClass().getSuperclass()))) {
return proxy.invokeSuper(obj, args);
}
return null;
}
if (configClass != enhancedClass) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Replacing bean definition '%s' existing class '%s' with " +
"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
//对配置类的beanDefinition的beanClass属性进行替换,替换成代理之后的Class对象
beanDef.setBeanClass(enhancedClass);
}
}
} catch (Throwable ex) {
throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}