ConfigurationClassPostProcessor类的作用
此类是一个后置处理器的类,主要功能是参与BeanFactory的建造,主要功能如下
1、解析加了@Configuration的配置类
2、解析@ComponentScan扫描的包
3、解析@ComponentScans扫描的包
4、解析@Import注解
执行代码
定义一个配置类
@Configuration
@ComponentScan(basePackages="com.mashibing.aop.annotation")
@EnableAspectJAutoProxy
public class SpringConfiguration { }
启动加载:
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfiguration.class);
加载ConfigurationClassPostProcessor类的定义信息生成RootBeanDefinition
调用链路
registerAnnotationConfigProcessors:172, AnnotationConfigUtils (org.springframework.context.annotation)
registerAnnotationConfigProcessors:138, AnnotationConfigUtils (org.springframework.context.annotation)
<init>:91, AnnotatedBeanDefinitionReader (org.springframework.context.annotation)
<init>:74, AnnotatedBeanDefinitionReader (org.springframework.context.annotation)
<init>:66, AnnotationConfigApplicationContext (org.springframework.context.annotation)
<init>:87, AnnotationConfigApplicationContext (org.springframework.context.annotation)
main:18, TestAnnotationAop (com.mashibing.aop.annotation)
注册的关键代码
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {// internalConfigurationAnnotationProcessor
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
// 注册BeanDefinition到注册表中 internalConfigurationAnnotationProcessor
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
这一步会把如下这些加载到factory的beannames中
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
最终在beanMap中,会有ConfigurationClassPostProcessor定义信息,该类是一个实现BeanDefinitionRegistryPostProcessor接口的类,后续会执行到:
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware
ConfigurationClassPostProcessor 的实例化
invokeBeanFactoryPostProcessors:109, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:812, AbstractApplicationContext (org.springframework.context.support)
refresh:590, AbstractApplicationContext (org.springframework.context.support)
<init>:89, AnnotationConfigApplicationContext (org.springframework.context.annotation)
main:18, TestAnnotationAop (com.mashibing.aop.annotation)
找到所有实现BeanDefinitionRegistryPostProcessor接口bean的beanName,获取名字对应的bean实例,添加到currentRegistryProcessors中
// 调用所有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类
// 找到所有实现BeanDefinitionRegistryPostProcessor接口bean的beanName
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 遍历处理所有符合规则的postProcessorNames
for (String ppName : postProcessorNames) {
// 检测是否实现了PriorityOrdered接口
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 获取名字对应的bean实例,添加到currentRegistryProcessors中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 将要被执行的BFPP名称添加到processedBeans,避免后续重复执行
processedBeans.add(ppName);
}
}
ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry执行
postProcessBeanDefinitionRegistry:239, ConfigurationClassPostProcessor (org.springframework.context.annotation)
invokeBeanDefinitionRegistryPostProcessors:412, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:123, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:812, AbstractApplicationContext (org.springframework.context.support)
refresh:590, AbstractApplicationContext (org.springframework.context.support)
<init>:89, AnnotationConfigApplicationContext (org.springframework.context.annotation)
main:18, TestAnnotationAop (com.mashibing.aop.annotation)
/**
* 定位、加载、解析、注册相关注解
*从注册中心的配置类派生更多的bean定义。
* Derive further bean definitions from the configuration classes in the registry.
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 根据对应的registry对象生成hashcode值,此对象只会操作一次,如果之前处理过则抛出异常
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);
}
// 将马上要进行处理的registry对象的id值放到已经处理的集合对象中
this.registriesPostProcessed.add(registryId);
// 处理配置类的bean定义信息
processConfigBeanDefinitions(registry);
}
processConfigBeanDefinitions处理配置类的注解定义信息,这里会把SpringConfiguration类进行解析,注解扫描到的类会生成bean的定义信息,后续实例化,spring注解生效的地方:
processConfigBeanDefinitions方法详解
/**
* 构建和验证一个类是否被@Configuration修饰,并做相关的解析工作
*
* 如果你对此方法了解清楚了,那么springboot的自动装配原理就清楚了
*
* Build and validate a configuration model based on the registry of
* {@link Configuration} classes.
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// 创建存放BeanDefinitionHolder的对象集合
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 当前registry就是DefaultListableBeanFactory,获取所有已经注册的BeanDefinition的beanName
String[] candidateNames = registry.getBeanDefinitionNames();
// 遍历所有要处理的beanDefinition的名称,筛选对应的beanDefinition(被注解修饰的)
for (String beanName : candidateNames) {
// 获取指定名称的BeanDefinition对象
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 如果beanDefinition中的configurationClass属性不等于空,那么意味着已经处理过,输出日志信息
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}//一定要被@Configuration注解修饰才行
// 判断当前BeanDefinition是否是一个配置类,并为BeanDefinition设置属性为lite或者full,此处设置属性值是为了后续进行调用
// 如果Configuration配置proxyBeanMethods代理为true则为full
// 如果加了@Bean、@Component、@ComponentScan、@Import、@ImportResource注解,则设置为lite
// 如果配置类上被@Order注解标注,则设置BeanDefinition的order属性值
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类型
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
// 类型的强制转换
sbr = (SingletonBeanRegistry) registry;
// 判断是否有自定义的beanName生成器
if (!this.localBeanNameGeneratorSet) {
// 获取自定义的beanName生成器
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
// 如果有自定义的命名生成策略
if (generator != null) {
//设置组件扫描的beanName生成策略
this.componentScanBeanNameGenerator = generator;
// 设置import bean name生成策略
this.importBeanNameGenerator = generator;
}
}
}
// 如果环境对象等于空,那么就重新创建新的环境对象
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
// 实例化ConfigurationClassParser类,并初始化相关的参数,完成配置类的解析工作
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 创建两个集合对象,
// 存放相关的BeanDefinitionHolder对象
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
// 存放扫描包下的所有bean
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {// @ComponentScan、@ComponentScans @PropertySources,@Component,、@Import、@ImportResource @Bean
// 解析带有@Controller、@Import、@ImportResource、@ComponentScan、@ComponentScans、@Bean的BeanDefinition
parser.parse(candidates);// 1. 解析配置类, 对@Component,@PropertySources,@ComponentScans,
// 将解析完的Configuration配置类进行校验,1、配置类不能是final,2、@Bean修饰的方法必须可以重写以支持CGLIB
parser.validate();
// 获取所有的bean,包括扫描的bean对象,@Import导入的bean对象
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
// 清除掉已经解析处理过的配置类
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
// 判断读取器是否为空,如果为空的话,就创建完全填充好的ConfigurationClass实例的读取器
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 核心方法,将完全填充好的ConfigurationClass实例转化为BeanDefinition注册入IOC容器
this.reader.loadBeanDefinitions(configClasses);
// 添加到已经处理的集合中
alreadyParsed.addAll(configClasses);
candidates.clear();
// 这里判断registry.getBeanDefinitionCount() > candidateNames.length的目的是为了知道reader.loadBeanDefinitions(configClasses)这一步有没有向BeanDefinitionMap中添加新的BeanDefinition
// 实际上就是看配置类(例如AppConfig类会向BeanDefinitionMap中添加bean)
// 如果有,registry.getBeanDefinitionCount()就会大于candidateNames.length
// 这样就需要再次遍历新加入的BeanDefinition,并判断这些bean是否已经被解析过了,如果未解析,需要重新进行解析
// 这里的AppConfig类向容器中添加的bean,实际上在parser.parse()这一步已经全部被解析了
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());
}
// 如果有未解析的类,则将其添加到candidates中,这样candidates不为空,就会进入到下一次的while的循环中
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();
}
}
- DefaultListableBeanFactory中获取所有已经注册的BeanDefinition的beanName
如果没被冻结就从beanDefinitionNames获取,否则是从frozenBeanDefinitionNames获取的。
public String[] getBeanDefinitionNames() {
String[] frozenNames = this.frozenBeanDefinitionNames;
if (frozenNames != null) {
return frozenNames.clone();
}
else {
return StringUtils.toStringArray(this.beanDefinitionNames);
}
}
执行这里不会被冻结,如果是实例化之前会被。
// 初始化剩下的单实例(非懒加载的)
finishBeanFactoryInitialization(beanFactory);
// 冻结所有的bean定义,说明注册的bean定义将不被修改或任何进一步的处理
beanFactory.freezeConfiguration();
public void freezeConfiguration() {
this.configurationFrozen = true;
this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}
- 然后根据这些beanName获取BeanDefinition,判断是否被注解@Configuration修饰为配置类,没被修饰不被处理。
被注解@Configuration修饰的放入configCandidates集合中,进行后续处理。
// 遍历所有要处理的beanDefinition的名称,筛选对应的beanDefinition(被注解修饰的)
for (String beanName : candidateNames) {
// 获取指定名称的BeanDefinition对象
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 如果beanDefinition中的configurationClass属性不等于空,那么意味着已经处理过,输出日志信息
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}//一定要被@Configuration注解修饰才行
// 判断当前BeanDefinition是否是一个配置类,并为BeanDefinition设置属性为lite或者full,此处设置属性值是为了后续进行调用
// 如果Configuration配置proxyBeanMethods代理为true则为full
// 如果加了@Bean、@Component、@ComponentScan、@Import、@ImportResource注解,则设置为lite
// 如果配置类上被@Order注解标注,则设置BeanDefinition的order属性值
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
// 添加到对应的集合对象中
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
ConfigurationClassUtils.checkConfigurationClassCandidate判断是否满足后续处理条件,
主要是判断这6个哪个满足条件,只有最后一个符合,因为:
ConfigurationClassPostProcessor和EventListenerMethodProcessor是BeanFactoryPostProcessor
AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor是BeanPostProcessor
DefaultEventListenerFactory是EventListenerFactory
这些条件不满足
if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) || //ConfigurationClassPostProcessor EventListenerMethodProcessor是bdrpp
BeanPostProcessor.class.isAssignableFrom(beanClass) ||//AutowiredAnnotationBeanPostProcessor CommonAnnotationBeanPostProcessor是bpp
AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
EventListenerFactory.class.isAssignableFrom(beanClass)) {//DefaultEventListenerFactory是EventListenerFactory
return false;
}
/**
* 检查当前给定的beanDefinition中是否是一个配置类的候选者,
* 判断在嵌套的关系中是否包含配置类或者组件类或者自动注册进去的,并做相应的标记
*/
public static boolean checkConfigurationClassCandidate(
BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
// 获取bean定义信息中的class类名
String className = beanDef.getBeanClassName();
// 如果className为空,或者bean定义信息中的factoryMethod不等于空,那么直接返回
if (className == null || beanDef.getFactoryMethodName() != null) {
return false;
}
AnnotationMetadata metadata;
// 通过注解注入的db都是AnnotatedGenericBeanDefinition,实现了AnnotatedBeanDefinition
// spring内部的bd是RootBeanDefinition,实现了AbstractBeanDefinition
// 此处主要用于判断是否归属于AnnotatedBeanDefinition
if (beanDef instanceof AnnotatedBeanDefinition &&
className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
// Can reuse the pre-parsed metadata from the given BeanDefinition...
// 从当前bean的定义信息中获取元数据信息
metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
}
// 判断是否是spring中默认的BeanDefinition
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.
// 获取当前bean对象的Class对象
Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
// 如果class实例是下面四种类或接口的子类、父接口等任何一种情况,直接返回
if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) || //ConfigurationClassPostProcessor EventListenerMethodProcessor是bdrpp
BeanPostProcessor.class.isAssignableFrom(beanClass) ||//AutowiredAnnotationBeanPostProcessor CommonAnnotationBeanPostProcessor是bpp
AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
EventListenerFactory.class.isAssignableFrom(beanClass)) {//DefaultEventListenerFactory是EventListenerFactory
return false;
}
// 为给定类创建新的AnnotationMetadata实例
metadata = AnnotationMetadata.introspect(beanClass);
}
// 如果上述两种情况都不符合
else {
try {
// 获取className的MetadataReader实例
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;
}
}
// 获取bean定义的元数据被@Configuration注解标注的属性字典值
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
// 如果bean被@Configuration注解标注,且属性proxyBeanMethods为false(使用代理模式),则将bean定义记为full
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
// 如果bean被@configuration注解标注,且被注解@Component,@ComponentScan、@Import、@ImportResource或者@Bean标记的方法,则将bean定义标记为lite
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.
// bean定义是一个标记为full或lite的候选项,如果设置order则设置order属性值
Integer order = getOrder(metadata);
// 如果值不为空的话,那么直接设置值到具体的beanDefinition
if (order != null) {
// 设置bean定义的order值
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
return true;
}
isConfigurationCandidate(metadata)的作用检查是否被注解@Component、@ComponentScan、@Import、@ImportResource标注,最后检查是否有@Bean标注的方法
// 定义set集合,用于存储标注配置类的注解 Component ComponentScan Import ImportResource
private static final Set<String> candidateIndicators = new HashSet<>(8);
static {
candidateIndicators.add(Component.class.getName());
candidateIndicators.add(ComponentScan.class.getName());
candidateIndicators.add(Import.class.getName());
candidateIndicators.add(ImportResource.class.getName());
}
/**
*
检查给定的元数据,以查找给定的候选配置类是否被指定的注解标注
*/
public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
// Do not consider an interface or an annotation...
// 不考虑接口或注解
if (metadata.isInterface()) {
return false;
}
// Any of the typical annotations found?
// 检查是否被注解@Component、@ComponentScan、@Import、@ImportResource标注
for (String indicator : candidateIndicators) {
if (metadata.isAnnotated(indicator)) {
return true;
}
}
// Finally, let's look for @Bean methods...
// 最后检查是否有@Bean标注的方法
try {
return metadata.hasAnnotatedMethods(Bean.class.getName());
}
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
}
return false;
}
}
configCandidates只有一个元素,后续对这个元素进行操纵:
parser.parse(candidates)开始执行
@ComponentScan、@ComponentScans @PropertySources,@Component,、@Import、@ImportResource @Bean
解析带有@Controller、@Import、@ImportResource、@ComponentScan、@ComponentScans、@Bean的BeanDefinition
// 创建两个集合对象,
// 存放相关的BeanDefinitionHolder对象
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
// 存放扫描包下的所有bean
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {// @ComponentScan、@ComponentScans @PropertySources,@Component,、@Import、@ImportResource @Bean
// 解析带有@Controller、@Import、@ImportResource、@ComponentScan、@ComponentScans、@Bean的BeanDefinition
parser.parse(candidates);// 1. 解析配置类, 对@Component,@PropertySources,@ComponentScans,
// 将解析完的Configuration配置类进行校验,1、配置类不能是final,2、@Bean修饰的方法必须可以重写以支持CGLIB
parser.validate();
// 获取所有的bean,包括扫描的bean对象,@Import导入的bean对象
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
// 清除掉已经解析处理过的配置类
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
// 判断读取器是否为空,如果为空的话,就创建完全填充好的ConfigurationClass实例的读取器
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 核心方法,将完全填充好的ConfigurationClass实例转化为BeanDefinition注册入IOC容器
this.reader.loadBeanDefinitions(configClasses);
// 添加到已经处理的集合中
alreadyParsed.addAll(configClasses);
candidates.clear();
// 这里判断registry.getBeanDefinitionCount() > candidateNames.length的目的是为了知道reader.loadBeanDefinitions(configClasses)这一步有没有向BeanDefinitionMap中添加新的BeanDefinition
// 实际上就是看配置类(例如AppConfig类会向BeanDefinitionMap中添加bean)
// 如果有,registry.getBeanDefinitionCount()就会大于candidateNames.length
// 这样就需要再次遍历新加入的BeanDefinition,并判断这些bean是否已经被解析过了,如果未解析,需要重新进行解析
// 这里的AppConfig类向容器中添加的bean,实际上在parser.parse()这一步已经全部被解析了
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());
}
// 如果有未解析的类,则将其添加到candidates中,这样candidates不为空,就会进入到下一次的while的循环中
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();
}
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
// 判断是否跳过解析 如果@bean修饰的方法上有@Conditional注解 并且里面的类不存在 就跳过 不实例化创建对象
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
// 第一次进入的时候,configurationClass的size为0,existingClass肯定为null,在此处处理configuration重复import
// 如果同一个配置类被处理两次,两次都属于被import的则合并导入类,返回,如果配置类不是被导入的,则移除旧的使用新的配置类
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
// 如果要处理的配置类configclass在已经分析处理的配置类记录中已存在,合并两者的importBy属性
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.
// 处理配置类,由于配置类可能存在父类(若父类的全类名是以java开头的,则除外),所有需要将configClass变成sourceClass去解析,然后返回sourceClass的父类。
// 如果此时父类为空,则不会进行while循环去解析,如果父类不为空,则会循环的去解析父类
// SourceClass的意义:简单的包装类,目的是为了以统一的方式去处理带有注解的类,不管这些类是如何加载的
// 如果无法理解,可以把它当做一个黑盒,不会影响看spring源码的主流程
SourceClass sourceClass = asSourceClass(configClass, filter);
do {
// 解析各种注解
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
// 将解析的配置类存储起来,这样回到parse方法时,能取到值
this.configurationClasses.put(configClass, configClass);
}
doProcessConfigurationClass:293, ConfigurationClassParser (org.springframework.context.annotation)
processConfigurationClass:272, ConfigurationClassParser (org.springframework.context.annotation)
parse:219, ConfigurationClassParser (org.springframework.context.annotation)
parse:179, ConfigurationClassParser (org.springframework.context.annotation)
processConfigBeanDefinitions:366, ConfigurationClassPostProcessor (org.springframework.context.annotation)
postProcessBeanDefinitionRegistry:252, ConfigurationClassPostProcessor (org.springframework.context.annotation)
invokeBeanDefinitionRegistryPostProcessors:412, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:123, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:812, AbstractApplicationContext (org.springframework.context.support)
refresh:590, AbstractApplicationContext (org.springframework.context.support)
<init>:89, AnnotationConfigApplicationContext (org.springframework.context.annotation)
main:18, TestAnnotationAop (com.mashibing.aop.annotation)
doProcessConfigurationClass
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
// @Configuration继承了@Component 如果当前类的注解是@Configuration会进去 但是其内部类不是一个配置类
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
// 递归处理内部类,因为内部类也是一个配置类,配置类上有@configuration注解,该注解继承@Component,if判断为true,调用processMemberClasses方法,递归解析配置类中的内部类
processMemberClasses(configClass, sourceClass, filter);
}
// Process any @PropertySource annotations
// 如果配置类上加了@PropertySource注解,那么就解析加载properties文件,并将属性添加到spring上下文中
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 @Configuration加@ComponentScan注解在这里扫描
// 处理@ComponentScan或者@ComponentScans注解,并将扫描包下的所有bean转换成填充后的 ConfigurationClass
// 此处就是将自定义的bean加载到IOC容器,因为扫描到的类可能也添加了@ComponentScan和@ComponentScans注解,因此需要进行递归解析
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
// 解析@ComponentScan和@ComponentScans配置的扫描的包所包含的类
// 比如 basePackages = com.mashibing, 那么在这一步会扫描出这个包及子包下的class,然后将其解析成BeanDefinition
// (BeanDefinition可以理解为等价于BeanDefinitionHolder)
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
// 通过上一步扫描包com.mashibing,有可能扫描出来的bean中可能也添加了ComponentScan或者ComponentScans注解.
//所以这里需要循环遍历一次,进行递归(parse),继续解析,直到解析出的类上没有ComponentScan和ComponentScans
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
// 判断是否是一个配置类,并设置full或lite属性
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
// 通过递归方法进行解析
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @Import annotations
// 处理@Import注解 导入额外的配置类 并且完成实例化工作
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// Process any @ImportResource annotations
// 处理@ImportResource注解,导入spring的配置文件
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
// 处理加了@Bean注解的方法,将@Bean方法转化为BeanMethod对象,保存再集合中
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
// 处理接口的默认方法实现,从jdk8开始,接口中的方法可以有自己的默认实现,因此如果这个接口的方法加了@Bean注解,也需要被解析
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;
}
如果当前类的注解是Component会进去 但是 @Configuration其内部类不是一个配置类
private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,
Predicate<String> filter) throws IOException {
// 找到内部类,内部类中也可能是一个配置类
Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
// 如果不等于空的话
if (!memberClasses.isEmpty()) {
List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
// 循环判断内部类是不是配置类
for (SourceClass memberClass : memberClasses) {
if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
!memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
candidates.add(memberClass);
}
}
// 对配置类进行排序操作
OrderComparator.sort(candidates);
// 遍历符合规则的类
for (SourceClass candidate : candidates) {
if (this.importStack.contains(configClass)) {
// 出现配置类循环导入,则直接报错
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
// 将配置类入栈
this.importStack.push(configClass);
try {
// 调用processConfigurationClass方法,因为内部类中还可能包含内部类,所以需要在做循环解析,实际工作中是不会有这中情况的
processConfigurationClass(candidate.asConfigClass(configClass), filter);
}
finally {
// 解析完出栈
this.importStack.pop();
}
}
}
}
}
解析@PropertySource注解
如果配置类上加了@PropertySource注解,那么就解析加载properties文件,并将属性添加到spring上下文中
// Process any @PropertySource annotations
// 如果配置类上加了@PropertySource注解,那么就解析加载properties文件,并将属性添加到spring上下文中
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");
}
}
处理@ComponentScan或者@ComponentScans注解
// Process any @ComponentScan annotations @Configuration加@ComponentScan注解在这里扫描
// 处理@ComponentScan或者@ComponentScans注解,并将扫描包下的所有bean转换成填充后的 ConfigurationClass
// 此处就是将自定义的bean加载到IOC容器,因为扫描到的类可能也添加了@ComponentScan和@ComponentScans注解,因此需要进行递归解析
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
// 解析@ComponentScan和@ComponentScans配置的扫描的包所包含的类
// 比如 basePackages = com.mashibing, 那么在这一步会扫描出这个包及子包下的class,然后将其解析成BeanDefinition
// (BeanDefinition可以理解为等价于BeanDefinitionHolder)
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
// 通过上一步扫描包com.mashibing,有可能扫描出来的bean中可能也添加了ComponentScan或者ComponentScans注解.
//所以这里需要循环遍历一次,进行递归(parse),继续解析,直到解析出的类上没有ComponentScan和ComponentScans
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
// 判断是否是一个配置类,并设置full或lite属性
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
// 通过递归方法进行解析
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
处理@Import注解 导入额外的配置类 并且完成实例化工作
// Process any @Import annotations
// 处理@Import注解 导入额外的配置类 并且完成实例化工作
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
// 创建集合,存储包含@Import注解的类
Set<SourceClass> imports = new LinkedHashSet<>();
// 创建集合,为了实现递归调用
Set<SourceClass> visited = new LinkedHashSet<>();
// 收集@Import注解的类
collectImports(sourceClass, imports, visited);
return imports;
}
//循环递归调用 方法上的所有注解执行一遍判断当前注解是是否是@Import 不是就继续递归这个注解 直到在类上的注解或者注解的注解上找到@Import注解并把里面的value加到imports
private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
throws IOException {
if (visited.add(sourceClass)) {
for (SourceClass annotation : sourceClass.getAnnotations()) {
String annName = annotation.getMetadata().getClassName();
// 递归处理其他可能包含@Import的注解类
if (!annName.equals(Import.class.getName())) {
collectImports(annotation, imports, visited);
}
}
// 获取Import注解的值
imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
}
}
@Import注解里面可以指定导入的类,例如:
@Import({AutoConfigurationImportSelector.class})
在SpringBoot中自动装配的实现原理就和这里有着密切的关联,@SpringBootApplication是启动类的注解。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
@AliasFor(
annotation = EnableAutoConfiguration.class
)
Class<?>[] exclude() default {};
@AliasFor(
annotation = EnableAutoConfiguration.class
)
String[] excludeName() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackages"
)
String[] scanBasePackages() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackageClasses"
)
Class<?>[] scanBasePackageClasses() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "nameGenerator"
)
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}
这个注解上面有个@EnableAutoConfiguration注解,@EnableAutoConfiguration这个注解上有个@Import({AutoConfigurationImportSelector.class})
,这里就会把AutoConfigurationImportSelector获取到传给processImports方法执行。
// 处理@Import注解 导入额外的配置类 并且完成实例化工作
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
boolean checkForCircularImports) {
// 如果使用@Import注解修饰的类集合为空,那么直接返回
if (importCandidates.isEmpty()) {
return;
}
// 通过一个栈结构解决循环引入
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
// 添加到栈中,用于处理循环引入的问题
this.importStack.push(configClass);
try {
// 遍历每一个@Import注解的类
for (SourceClass candidate : importCandidates) {
// 检验配置类Import引入的类是否是ImportSelector子类
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
// 候选类是一个导入选择器->委托来确定是否进行导入
Class<?> candidateClass = candidate.loadClass();
// 通过反射生成一个ImportSelect对象 实例化引入的 ImportSelector,并且会执行 Aware 接口方法 实例化
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);//支持的Aware有BeanClassLoaderAware,BeanFactoryAware,EnvironmentAware,ResourceLoaderAware
// 获取选择器的额外过滤器
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
// 判断引用选择器是否是DeferredImportSelector接口的实例
// 如果是则应用选择器将会在所有的配置类都加载完毕后加载
if (selector instanceof DeferredImportSelector) {
// 将选择器添加到deferredImportSelectorHandler实例中,预留到所有的配置类加载完成后统一处理自动化配置类 延迟处理
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
// 获取引入的类,然后使用递归方式将这些类中同样添加了@Import注解引用的类
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
// 递归处理,被Import进来的类也有可能@Import注解
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
}
// 如果是实现了ImportBeanDefinitionRegistrar接口的bd
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
// 候选类是ImportBeanDefinitionRegistrar -> 委托给当前注册器注册其他bean
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
/**
* 放到当前configClass的importBeanDefinitionRegistrars中
* 在ConfigurationClassPostProcessor处理configClass时会随之一起处理
*/
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
// 候选类既不是ImportSelector也不是ImportBeanDefinitionRegistrar-->将其作为@Configuration配置类处理
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
/**
* 如果Import的类型是普通类,则将其当作带有@Configuration的类一样处理
* 将candidate构造为ConfigurationClass,标注为importedBy,意味着它是通过被@Import进来的
* 后面处理会用到这个判断将这个普通类注册进DefaultListableBeanFactory
*/
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
}
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();
}
}
}
因为AutoConfigurationImportSelector 实现DeferredImportSelector接口,所以会执行到:
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
放到deferredImportSelectors集合中去
public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
if (this.deferredImportSelectors == null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
handler.register(holder);
handler.processGroupImports();
}
else {
this.deferredImportSelectors.add(holder);
}
}
parse:179, ConfigurationClassParser (org.springframework.context.annotation)
processConfigBeanDefinitions:366, ConfigurationClassPostProcessor (org.springframework.context.annotation)
postProcessBeanDefinitionRegistry:252, ConfigurationClassPostProcessor (org.springframework.context.annotation)
invokeBeanDefinitionRegistryPostProcessors:412, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:123, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:812, AbstractApplicationContext (org.springframework.context.support)
refresh:590, AbstractApplicationContext (org.springframework.context.support)
<init>:89, AnnotationConfigApplicationContext (org.springframework.context.annotation)
main:18, TestAnnotationAop (com.mashibing.aop.annotation)
ConfigurationClassParser 的parse方法,会执行deferredImportSelectorHandler添加的
public void parse(Set<BeanDefinitionHolder> configCandidates) {
// 循环遍历configCandidates
for (BeanDefinitionHolder holder : configCandidates) {
// 获取BeanDefinition
BeanDefinition bd = holder.getBeanDefinition();
// 根据BeanDefinition类型的不同,调用parse不同的重载方法,实际上最终都是调用processConfigurationClass()方法
try {
// 注解类型
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
// 有class对象的
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
// 执行找到的DeferredImportSelector
// DeferredImportSelector是ImportSelector的一个子类
// ImportSelector被设计成和@Import注解同样的效果,但是实现了ImportSelector的类可以条件性的决定导入某些配置
// DeferredImportSelector的设计魔都是在所有其他的配置类被处理后才进行处理
this.deferredImportSelectorHandler.process();
}
this.deferredImportSelectorHandler.process()执行:
public void process() {
// 此处获取@Import注解导入器
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
deferredImports.forEach(handler::register);
// 核心处理类,此处完成自动配置功能
handler.processGroupImports();
}
}
finally {
this.deferredImportSelectors = new ArrayList<>();
}
}
// 核心处理类,此处完成自动配置功能
handler.processGroupImports();
public void processGroupImports() {
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
Predicate<String> exclusionFilter = grouping.getCandidateFilter();
// getImports方法是读取自动化配置类的核心入口, // 遍历分组, grouping.getImports()是关键
grouping.getImports().forEach(entry -> {
ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
try { // 同ImportSelector的实现类一样,最终也是调用 processImports(...) 处理导入
// 配置类中可能会包含@Import注解引入的类,通过此方法将引入的类注入 // 注意 entry.getImportClassName(),这一次调用 processImports(...) 的参
processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter), // 数是ImportSelector引入的类
Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
exclusionFilter, false);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configurationClass.getMetadata().getClassName() + "]", ex);
}
});
}
}
grouping.getImports()
/**
* Return the imports defined by the group.
* @return each import with its associated configuration class
*/
public Iterable<Group.Entry> getImports() {
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
// 核心方法,在springboot中此方法会去SpringFactoriesLoader类中加载自动化配置类
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
// 获取已经取得的配置类
return this.group.selectImports();
}
this.group.process
这里获取的EnableAutoConfiguration就是META-INF/spring.factories文件下key对应的自动装配要加载的东西,这个文件哪里来,看下文:
public static final String FACTORIES_RESOURCE_LOCATION = “META-INF/spring.factories”;
从这个文件下加载读取资源,这个文件下存储的什么??
这里去除key
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnClassCondition
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,\
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer
# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider
可以看出META-INF/spring.factories这个文件加载之后EnableAutoConfiguration对应的value,这些就是自动装配要加载的东西了。
,到这里自动装配也结合Spring把核心讲完了。
@ImportResource、@Bean注解的方法的解析加载
// Process any @ImportResource annotations
// 处理@ImportResource注解,导入spring的配置文件
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
// 处理加了@Bean注解的方法,将@Bean方法转化为BeanMethod对象,保存再集合中
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
// 处理接口的默认方法实现,从jdk8开始,接口中的方法可以有自己的默认实现,因此如果这个接口的方法加了@Bean注解,也需要被解析
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();
}
}
至此Spring注解解析加载的源码就结束了,伴随着springboot自动装配讲解,学起来!!!