1. 简介
本篇文章是对上一篇文章Spring刷新应用上下文的补充说明,详细讲述了上一篇文章中的第五步(实例化并调用所有注册的beanFactory后置处理器)中Spring解析@Configuration注解的过程。
在Spring3.0之前的Spring核心框架中,我们启动一个Spring容器必须使用一个XML文件。而到了3.0之后的版本Spring为创建容器新增了一个入口类——AnnotationConfigApplicationContext。AnnotationConfigApplicationContext和过去的ClassPathXmlApplicationContext、FileSystemXmlApplicationContext等方法不同的是他不用再指定任何XML配置文件,而是可以通过指定类向容器添加Bean。
因此,从Spring3.0后,只要在配置类上加@Configuration注解就可以替换之前的xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。从使用的角度来说可以把他理解为XML配置中的<beans>标签,但是二者又有些细节的差异。在<beans>标签中除了使用<bean>声名Bean以外,还有各种<context>标签来扩展功能,比如<context:component-scan/>、<context:annotation-config />以及<import>等,这些扩展的功能并不是@Configuration注解的参数,而是通过其它注解来实现的如:@ComponentScan、@Import。
1.1 前提
使用@Configuration注解需满足以下要求
- @Configuration不可以是final类型;
- @Configuration不可以是匿名类;
- 嵌套的configuration必须是静态类。
1.2 声明
Spring对@Configuration注解类的解析最终是在ConfigurationClassPostProcessor类调用的processConfigBeanDefinitions方法中使用Spring的工具类ConfigurationClassParser来进行的。ConfigurationClassPostProcessor类是BeanFactoryPostProcessor的实现(看下图),BeanFactoryPostProcessor用于spring应用启动过程中@Configuration类的处理(发现和处理所有的配置类,注册其中的bean定义)。
1.3 @Configuration源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
@AliasFor(annotation = Component.class)
String value() default ""; //可以自定义Bean的名称
}
2 @Configuration类的解析
介绍
ConfigurationClassPostProcessor 位于 org.springframework.context.annotation 包中,这是一个 BeanDefinitionRegistryPostProcessor,隐含地也实现了接口BeanFactoryPostProcessor,用于spring 应用启动过程中 @Configuration 类的处理(发现和处理所有的配置类,注册其中的bean定义)。
引入时机
- 非Springboot的Sping应用,当在配置文件中使用<context:annotation-config/>或者 <context:component-scan/>时,该BeanFactoryPostProcessor会被注册。
- Springboot 应用中在ApplicationContext对象创建时,会在应用上下文类(参考AnnotationConfigServletWebServerApplicationContext/AnnotationConfigReactiveWebServerApplicationContext)的构造函数中创建AnnotatedBeanDefinitionReader对象时调用 AnnotationConfigUtils.registerAnnotationConfigProcessors() 注册这个BeanFactoryPostProcessor到容器。
调用时机
ConfigurationClassPostProcessor既实现了BeanDefinitionRegistryPostProcessor定义的方法postProcessBeanDefinitionRegistry,也实现了接口BeanFactoryPostProcessor定义的方法postProcessBeanFactory。
AbstractApplicationContext.refresh()方法执行时,在BeanFactory,也就是Spring容器被准备(prepare)和postProcess之后,AbstractApplicationContext的invokeBeanFactoryPostProcessors()方法被调用,这个方法用来执行所有容器中被作为bean注册的BeanFactoryPostProcessor,其中就包括对ConfigurationClassPostProcessor方法postProcessBeanDefinitionRegistry()以及postProcessBeanFactory()方法的调用。
调用过程
解析过程是在容器刷新方法中--refreshContext(context) --> refresh(context) --> ApplicationContext.refresh()
--> invokeBeanFactoryPostProcessor(beanFactory)(该方法在容器刷新专栏有详细讲解,就是调用了PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors方法)这个方法调用所有的BeanFactoryPostProcessor,同时也就启动了Configuration类的解析。此时的BeanFactory中已经加载了main class,以及内部定义的class。内部定义的class都是带internal的,这些并不是Configuration Class,解析程序会忽略这些类,最后只有SpringBoot的启动类(如:DemoApplication)会进行Configuration的解析处理。
这里之所有这样做的原因是上述方法执行时有可能注册新的BeanDefinitionRegistryPostProcessor/BeanFactoryPostProcessor到容器,而这些新注册的BeanDefinitionRegistryPostProcessor/BeanFactoryPostProcessor也需要在这个阶段执行。
注意事项
- BeanDefinitionRegistryPostProcessor可能会注册另外一个BeanDefinitionRegistryPostProcessor。
- 一个非BeanDefinitionRegistryPostProcessor BeanFactoryPostProcessor可能会注册另外一个BeanFactoryPostProcessor。
- 一个非BeanDefinitionRegistryPostProcessor BeanFactoryPostProcessor不会注册另外一个BeanDefinitionRegistryPostProcessor(注册了但是不会被执行)。
因为配置类中定义的每个bean定义方法都必须要赶在其它BeanFactoryPostProcessor应用前,所以完成bean定义注册任务的ConfigurationClassPostProcessor 被设计为拥有最高执行优先级Ordered.HIGHEST_PRECEDENCE。
2.1 开始看代码
重提上一篇文章Spring 刷新应用上下文中的invokeBeanFactoryPostProcessors方法,用以引出下文。
//实例化并调用所有注册的beanFactory后置处理器
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();
//遍历所有的beanFactoryPostProcessors,
//将BeanDefinitionRegistryPostProcessor和普通BeanFactoryPostProcessor区分开
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//主要看这里!!!
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
....省略此处代码在之前的文章已经介绍过了
该方法主要做了以下事情:
- 执行了BeanDefinitionRegistryPostProcessor(此处只有ConfigurationClassPostProcessor)
- 执行了BeanFactoryPostProcessor
- 完成了@Configuration配置文件的解析,并且把扫描到的、配置的Bean定义信息都加载进容器里
- Full模式下,完成了对@Configuration配置文件的加强,使得管理Bean依赖关系更加的方便了
registryProcessor.postProcessBeanDefinitionRegistry(registry)这一步(调用了ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry方法)使用工具ConfigurationClassParser尝试发现所有的配置(@Configuration)类,使用工具ConfigurationClassBeanDefinitionReader注册所发现的配置类中所有的bean定义。结束执行的条件是所有配置类都被发现和处理,相应的bean定义注册到容器。
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
2.2 主要看这里
下面看ConfigurationClassPostProcessor类中postProcessBeanDefinitionRegistry()的处理逻辑,该方法使用工具ConfigurationClassParser尝试发现所有的配置(@Configuration)类,使用工具ConfigurationClassBeanDefinitionReader注册所发现的配置类中所有的bean定义。结束执行的条件是所有配置类都被发现和处理,相应的bean定义注册到容器。
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
//根据BeanDefinitionRegistry,生成registryId 是全局唯一的。
int registryId = System.identityHashCode(registry);
// 判断,如果这个registryId 已经被执行过了,就不能够再执行了,否则抛出异常
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防止重复执行
this.registriesPostProcessed.add(registryId);
// 调用processConfigBeanDefinitions 进行Bean定义的加载
processConfigBeanDefinitions(registry);
}
2.2.1 处理配置类并注册BeanDefinition
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
// 记录候选配置类
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 获取已经注册的bean名称(将容器中已经登记的Bean定义作为候选配置类名称)
String[] candidateNames = registry.getBeanDefinitionNames();
// 程序此时处于容器启动的早期,通常此时 candidateNames 中实际上只会有一个配置类(即...Application启动类)
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//如果beanDef现在就已经确定了是full或者lite,说明已经被解析过了,所以再来就直接输出debug
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
// 检查是否是@Configuration的Class,如果是就标记下属性:full 或者lite。
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
//如果当前的bean是Javabean配置类(含有@Configuration注解的类),则加入到集合configCandidates中
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 如果一个配置文件类都没找到,直接返回
if (configCandidates.isEmpty()) {
return;
}
// 把这些配置按照@Order注解进行排序(@Configuration注解的配置文件是支持order排序的。但是普通bean不行)
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// 尝试检测自定义的 BeanNameGenerator
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;
}
}
}
// web环境这里都设置了StandardServletEnvironment
//正常情况下env环境不可能为null(此处做容错处理)
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// ConfigurationClassParser是真正解析@Configuration注解的类
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 表示将要被处理的候选配置类
// 因为不清楚候选是否确实是配置类,所以使用BeanDefinitionHolder类型记录
// 这里初始化为方法开始时容器中注解了@Configuration的Bean定义的集合
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
// 装载已经处理过的配置类,最大长度为:configCandidates.size()
// 表示已经处理的配置类,已经被处理的配置类已经明确了其类型,所以用 ConfigurationClass 类型记录,
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
// 解析目标配置类【第一个解析的是应用程序主类】
parser.parse(candidates);
// 主要校验配置类不能使用final修饰符(CGLIB代理是生成一个子类,因此原先的类不能使用final修饰)
parser.validate();
// 从分析器parser中获取分析得到的配置类configurationClasses
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// 如果Reader为null,那就实例化ConfigurationClassBeanDefinitionReader来加载Bean,
// 并加入到alreadyParsed中,用于去重(避免@ComponentScan直接互扫)
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 此处调用ConfigurationClassBeanDefinitionReader的loadBeanDefinitionsd方法
// 加载配置文件里面的@Bean/@Import,此方法决定了向容器注册Bean定义信息的顺序
this.reader.loadBeanDefinitions(configClasses);
// 刚刚处理完的配置类记录到已处理配置类alreadyParsed集合中
alreadyParsed.addAll(configClasses);
// 清空候选配置类集合,为下一轮do循环做初始化准备
candidates.clear();
// 如果registry中注册的bean的数量 大于 之前获得的数量
if (registry.getBeanDefinitionCount() > candidateNames.length) {
// 则意味着在解析过程中发现并注册了更多的Bean定义到容器中去,这些新注册的Bean定义
// 也有可能是候选配置类,它们也要被处理用来发现和注册Bean定义
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) {
// 如果老的oldCandidateNames不包含就说明是新进来的候选的Bean定义(即当前 BeanDefinition 是新解析的)
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
// 基于 BeanDefinition 创建 BeanDefinitionHolder 并将其写入 candidates
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());// 直到所有的配置类都解析完毕
// 注册 ImportRegistry bean 到 SingletonBeanRegistry 中
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
//清除缓存(元数据缓存)
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
下面文章主要围绕processConfigBeanDefinitions方法做的扩展延伸。
3 解析processConfigBeanDefinitions方法
3.1 概要分析
处理配置类并注册BeanDefinition的方法比较复杂,下面针对方法中一些重要的功能点进行解析:
3.2. 介绍ConfigurationClassUtils工具类
3.3. 解析Java配置类ConfigurationClassParser#parse(Set<BeanDefinitionHolder> configCandidates)
3.3.1 processConfigurationClass解析单个配置类
3.3.1.1 doProcessConfigurationClass
3.3.1.1.1 processMemberClasses
3.3.1.1.2 处理给定的@PropertySource 注解元数据
3.3.1.1.3 @ComponentScan注解解析过程
3.3.1.1.3 processImports
3.3.1.1.5 processInterfaces
3.3.1.2 ConditionEvaluator条件评估
3.3.1.3 ConfigurationClass配置类
3.3.1.4 ConditionalOnProperty
3.4. loadBeanDefinitions加载bean定义信息
3.2 ConfigurationClassUtils工具类
ConfigurationClassUtils工具类用于检查是否是含有@Configuration注解的类,需要注意下面两个核心方法,是如何判断某个类是否为配置类的(判断是full模式,还是lite模式的配置文件):
- 如果类上有@Configuration注解说明是一个完全(Full)的配置类
- 如果如果类上面有@Component,@ComponentScan,@Import,@ImportResource这些注解,那么就是一个简化配置类。如果不是上面两种情况,那么有@Bean注解修饰的方法也是简化配置类
abstract class ConfigurationClassUtils {
private static final String CONFIGURATION_CLASS_FULL = "full";
private static final String CONFIGURATION_CLASS_LITE = "lite";
private static final String CONFIGURATION_CLASS_ATTRIBUTE =
Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "configurationClass");
private static final String ORDER_ATTRIBUTE =
Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "order");
private static final Log logger = LogFactory.getLog(ConfigurationClassUtils.class);
private static final Set<String> candidateIndicators = new HashSet<>(4);
static {
candidateIndicators.add(Component.class.getName());
candidateIndicators.add(ComponentScan.class.getName());
candidateIndicators.add(Import.class.getName());
candidateIndicators.add(ImportResource.class.getName());
}
// 只要这个类标注了:@Configuration注解就行(接口、抽象类都没问题)
public static boolean isFullConfigurationCandidate(AnnotationMetadata metadata) {
return metadata.isAnnotated(Configuration.class.getName());
}
// 判断是Lite模式的条件:(首先肯定没有@Configuration注解)
// 1、不能是接口
// 2、但凡只要标注了一个下面注解,都算lite模式:@Component @ComponentScan @Import @ImportResource
// 3、只要存在有一个方法标注了@Bean注解,那就是lite模式
public static boolean isLiteConfigurationCandidate(AnnotationMetadata metadata) {
// 不能是接口
if (metadata.isInterface()) {
return false;
}
// 但凡只有标注了一个下面注解,都算lite模式:@Component @ComponentScan @Import @ImportResource
for (String indicator : candidateIndicators) {
if (metadata.isAnnotated(indicator)) {
return true;
}
}
// 只有存在有一个方法标注了@Bean注解,那就是lite模式
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;
}
}
// 不管是Full模式还是Lite模式,都被认为是候选的配置类,是上面两个方法的结合
public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
return (isFullConfigurationCandidate(metadata) || isLiteConfigurationCandidate(metadata));
}
// 下面两个方法是直接判断Bean定义信息,是否是配置类,至于Bean定义里这个属性什么时候放进去的,请参考
//ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)方法,
//它会对每个Bean定义信息进行检测(毕竟刚开始Bean定义信息是非常少的,所以速度也很快)
public static boolean isFullConfigurationClass(BeanDefinition beanDef) {
return CONFIGURATION_CLASS_FULL.equals(beanDef.getAttribute(CONFIGURATION_CLASS_ATTRIBUTE));
}
public static boolean isLiteConfigurationClass(BeanDefinition beanDef) {
return CONFIGURATION_CLASS_LITE.equals(beanDef.getAttribute(CONFIGURATION_CLASS_ATTRIBUTE));
}
Full模式和Lite模式的区别:
- 当@Bean方法声明在没有被@Conguration注解的类里,这就是所谓的以’精简’模式(Lite)处理。例如,在一个@Component中,甚至在一个普通的类中声明的bean方法都会以’精简’处理。
- 跟完整@Configuration不同的是,精简@Bean方法难以声明bean之间的依赖。通常,在精简模式中操作时,不应该在一个@Bean方法中调用另一个@Bean方法。一种推荐的方式是只在@Configuration类中使用@Bean方法,这样可以确保总是使用’完整’模式,避免@Bean方法意外地被调用多次,减少那些在精简模式下产生的很难跟踪的微妙bugs。
例如:
@Configuration
public class AppConfig {
@Bean
public Foo foo() {
return new Foo(bar()); // 这里调用的bar()方法
}
@Bean
public Bar bar() {
return new Bar();
}
}
Foo 接受一个bar的引用来进行构造器注入:这种方法声明的bean的依赖关系只有在@Configuration类的@Bean方法中有效。如果换成@Component(Lite模式),则foo()方法中new Foo(bar())传入的bar()方法会每次产生一个新的Bar对象
结论:
在@Component或其他组建中使用@Bean好处是不会启动CGLIB这种重量级工具(不过在Spring中即使这里不使用,其他很多地方也在使用)。并且@Component及其相关的Stereotype组件自身就有摸框级别的功能,在这里使用@Bean注解能很好的表明一个Bean的从属和结构关系,但是需要注意直接调用方法的“副作用”。
个人建议如果没什么特别的要求就使用@Configuration,引入CGLIB并不会影响多少性能,然而坑会少很多。在spring官网将用@Configuration创建的@Bean称呼为"Full"模式、将@Component创建的@Bean称呼为"'lite"模式,从字面上也能略知他们的差异。
只有类上标注@Configuration才是full模式。标注有@Component、@ComponentScan、@Import、@ImportResource或者啥注解都没标注但是有被标注了@Bean的方法这种也是lite模式
3.3 解析Java配置类
解过程中
- 如果遇到注解了@Component类,直接作为Bean定义注册到容器
- 如果注解或者注解的注解中有@Import, 处理所有这些@import,识别配置类,添加到分析器的属性configurationClasses中去
ConfigurationClassParser#parse
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<>();
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
// 下面三种方式解析Bean
try {
// 我们使用的注解驱动,所以会到这个parse进来处理。
if (bd instanceof AnnotatedBeanDefinition) {
// 其实内部调用都是processConfigurationClass进行解析的
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
//只要有注解标注的,都会走这里来解析
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);
}
}
//处理ImportSelect,执行找到的 DeferredImportSelector
//DeferredImportSelector 是 ImportSelector 的一个变种。
// ImportSelector 被设计成其实和@Import注解的类同样的导入效果,但是实现 ImportSelector
// 的类可以条件性地决定导入哪些配置。
// DeferredImportSelector 的设计目的是在所有其他的配置类被处理后才处理。这也正是
// 该语句被放到本函数最后一行的原因。
processDeferredImportSelectors();
}
该方法做了三件事如下:
- 实例化deferredImportSelectors
- 遍历configCandidates ,进行处理.根据BeanDefinition 的类型 做不同的处理,一般都会调用ConfigurationClassParser#parse 进行解析
- 处理ImportSelect
3.3.1 处理@Configuration配置类
解析@Configuration配置文件,然后加载进Bean的定义信息。可以看到它加载Bean定义信息的一个顺序
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
//ConfigurationCondition继承自Condition接口
// ConfigurationPhase枚举类型的作用:根据条件来判断是否加载这个配置类
// 两个值:PARSE_CONFIGURATION 若条件不匹配就不加载此@Configuration
// REGISTER_BEAN:无论如何,所有@Configurations都将被解析。
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
//判断同一个配置类是否重复加载过,如果重复加载过
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
//如果这个配置类已经存在了,后面又被@Import进来了就会走这里,然后做属性合并
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
return;
}
else {
//从集合中移除旧的配置类,后续逻辑将处理新的配置
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
SourceClass sourceClass = asSourceClass(configClass);
do {
//【doProcessConfigurationClass】这个方法是解析配置文件的核心方法
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
//保存我们所有的配置类(注意:它是一个LinkedHashMap,所以是有序的和bean定义信息息息相关)
this.configurationClasses.put(configClass, configClass);
}
3.3.1.1 doProcessConfigurationClass
doProcessConfigurationClass方法主要实现从配置类中解析所有bean,包括处理内部类,父类以及各种注解
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
//配置类上存在 Component注解,则尝试递归处理其内部成员类
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
processMemberClasses(configClass, sourceClass);
}
//处理所有 @PropertySource 注解:将目标资源导入到 environment.propertySources 中
//将所有的 @PropertySource 注解合并到 @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.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
//处理所有的 ComponentScan 注解
//以深度优先的方式递归处理所有扫描到的配置类
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
//循环处理每个 ComponentScan 注解
for (AnnotationAttributes componentScan : componentScans) {
//如果此配置类存在ComponentScan注解,则通过 ComponentScanAnnotationParser立即处理它
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// 遍历扫描到的所有组件
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
//若果扫描出的bean定义是配置类(含有@COnfiguration)
if (ConfigurationClassUtils.checkConfigurationClassCandidate(
holder.getBeanDefinition(), this.metadataReaderFactory)) {
//继续调用parse,内部再次调用doProcessConfigurationClas()递归解析
parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
}
}
}
}
//处理所有的 @Import 注解
//1.优先处理所有注解上的 @Import 注解导入的配置类
//2.后处理此类上通过@Import 注解直接导入的配置类
processImports(configClass, sourceClass, getImports(sourceClass), true);
//处理@ImportResource注解
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
// 读取资源位置
String[] resources = importResource.getStringArray("locations");
// 读取 BeanDefinitionReader
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
// 解析占位符
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
// 写入缓存
configClass.addImportedResource(resolvedResource, readerClass);
}
}
//处理所有的 @Bean 方法,将它们解析为 BeanMethod 并写入配置类中
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
//将解析出的所有@Bean注解方法添加到configClass配置类信息中
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
//处理所有接口上非 Abstract 的 @Bean 方法,并添加到configClass配置类信息中
processInterfaces(configClass, sourceClass);
// 如果有父类,则返回父类,递归执行doProcessConfigurationClass()解析父类
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();
}
}
// 此配置类处理完成
return null;
}
3.3.1.1.1 processMemberClasses
private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass) 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);
}
}
// 根据 Order 进行排序
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(candidate.asConfigClass(configClass));
}
finally {
//解析完成后将其出栈
this.importStack.pop();
}
}
}
}
}
3.3.1.1.2 处理给定的@PropertySource 注解元数据
private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
// 读取名称
String name = propertySource.getString("name");
if (!StringUtils.hasLength(name)) {
name = null;
}
// 读取编码
String encoding = propertySource.getString("encoding");
if (!StringUtils.hasLength(encoding)) {
encoding = null;
}
// 读取资源位置
String[] locations = propertySource.getStringArray("value");
Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
// 读取资源未找到则忽略标识
boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
// 读取 PropertySourceFactory
Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
// 循环处理每个资源
for (String location : locations) {
try {
// 解析占位符
String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
// 读取资源
Resource resource = this.resourceLoader.getResource(resolvedLocation);
// 创建 ResourcePropertySource 并加入到 environment 中
addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
}
catch (IllegalArgumentException | FileNotFoundException | UnknownHostException ex) {
// 占位符解析失败或资源未找到
if (ignoreResourceNotFound) {
if (logger.isInfoEnabled()) {
logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
}
}
else {
throw ex;
}
}
}
}
3.3.1.1.3 @ComponentScan注解解析过程
@ComponentScan注解解析通过调用ComponentScanAnnotationParser的parse方法完成,而parse()方法内部处理了一些scanner属性(过滤器设置)和basePackages包名处理,最终通过调用ClassPathBeanDefinitionScanner.doScan方法实现扫面工作。
3.3.1.1.3.1 ComponentScan 注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
/**
* 基础包名称
*/
@AliasFor("basePackages")
String[] value() default {};
/**
* 基础包名称
*/
@AliasFor("value")
String[] basePackages() default {};
/**
* 基础包类【读取指定类所在的包路径】
*/
Class<?>[] basePackageClasses() default {};
/**
* 用于生成 bean 名称的 BeanNameGenerator
*/
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
/**
* 范围解析器
*/
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
/**
* 是否需要为目标组件生成代理,默认不生成
*/
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
/**
* 资源模式
*/
String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
/**
* 是否使用默认的过滤器
* 自动检测 @Component、@Repository、@Service、@Controller 注解标注的类
*/
boolean useDefaultFilters() default true;
/**
* 指定扫描哪些类型
*/
Filter[] includeFilters() default {};
/**
* 指定排除哪些类型
*/
Filter[] excludeFilters() default {};
/**
* 扫描到的单例 bean 是否需要延迟初始化
*/
boolean lazyInit() default false;
@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {
/**
* 过滤类型,默认是基于注解
*/
FilterType type() default FilterType.ANNOTATION;
/**
* 用作筛选器的类,多个类之间是逻辑或的关系
*/
@AliasFor("classes")
Class<?>[] value() default {};
/**
* 用作筛选器的类,多个类之间是逻辑或的关系
*/
@AliasFor("value")
Class<?>[] classes() default {};
/**
* 匹配模式,根据 FilterType 分流
*/
String[] pattern() default {};
}
}
3.3.1.1.3.2 ComponentScan 注解解析器
/**
* @ComponentScan 注解解析器
*/
class ComponentScanAnnotationParser {
private final Environment environment;
private final ResourceLoader resourceLoader;
private final BeanNameGenerator beanNameGenerator;
private final BeanDefinitionRegistry registry;
public ComponentScanAnnotationParser(Environment environment, ResourceLoader resourceLoader,
BeanNameGenerator beanNameGenerator, BeanDefinitionRegistry registry) {
this.environment = environment;
this.resourceLoader = resourceLoader;
this.beanNameGenerator = beanNameGenerator;
this.registry = registry;
}
/**
* 解析指定的 @ComponentScan 注解
*/
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
// 类路径 BeanDefinition 扫描器
final ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry,
componentScan.getBoolean("useDefaultFilters"), environment, resourceLoader);
// 设置扫描器的 BeanNameGenerator
final Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
final boolean useInheritedGenerator = BeanNameGenerator.class == generatorClass;
scanner.setBeanNameGenerator(useInheritedGenerator ? beanNameGenerator :
BeanUtils.instantiateClass(generatorClass));
// 尝试设置扫描器的 ScopedProxyMode
final ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
scanner.setScopedProxyMode(scopedProxyMode);
}
else {
final Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
}
// 设置扫描器的资源模式
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
// 添加包含过滤器,默认无
for (final AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
for (final TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addIncludeFilter(typeFilter);
}
}
// 添加排序过滤器
for (final AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
for (final TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addExcludeFilter(typeFilter);
}
}
// 设置延迟初始化属性
final boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
scanner.getBeanDefinitionDefaults().setLazyInit(true);
}
final Set<String> basePackages = new LinkedHashSet<>();
// 尝试读取 basePackages 属性
final String[] basePackagesArray = componentScan.getStringArray("basePackages");
for (final String pkg : basePackagesArray) {
// 解析占位符,并按照 ,;\t\n 切割包路径
final String[] tokenized = StringUtils.tokenizeToStringArray(environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
Collections.addAll(basePackages, tokenized);
}
// 读取 basePackageClasses,并提取出包路径
for (final Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
/**
* 如果 basePackages 和 basePackageClasses 都未配置,
* 则以 @ComponentScan 注解所在配置类的包路径作为基础包
*/
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
// 忽略此配置类
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
@Override
protected boolean matchClassName(String className) {
return declaringClass.equals(className);
}
});
// 执行包扫描
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
private List<TypeFilter> typeFiltersFor(AnnotationAttributes filterAttributes) {
final List<TypeFilter> typeFilters = new ArrayList<>();
// 读取过滤类型
final FilterType filterType = filterAttributes.getEnum("type");
// 读取所有的 classes
for (final Class<?> filterClass : filterAttributes.getClassArray("classes")) {
switch (filterType) {
// 1)过滤类型为基于注解
case ANNOTATION:
// 目标 class 是否是注解
Assert.isAssignable(Annotation.class, filterClass,
"@ComponentScan ANNOTATION type filter requires an annotation type");
@SuppressWarnings("unchecked") final
Class<Annotation> annotationType = (Class<Annotation>) filterClass;
// 添加注解类型过滤器
typeFilters.add(new AnnotationTypeFilter(annotationType));
break;
// 2)过滤类型为基于目标类型及其子类
case ASSIGNABLE_TYPE:
// 添加类型过滤器
typeFilters.add(new AssignableTypeFilter(filterClass));
break;
// 3)过滤类型为基于自定义过滤器
case CUSTOM:
// 添加自定义 TypeFilter
Assert.isAssignable(TypeFilter.class, filterClass,
"@ComponentScan CUSTOM type filter requires a TypeFilter implementation");
final TypeFilter filter = BeanUtils.instantiateClass(filterClass, TypeFilter.class);
ParserStrategyUtils.invokeAwareMethods(
filter, environment, resourceLoader, registry);
typeFilters.add(filter);
break;
default:
throw new IllegalArgumentException("Filter type not supported with Class value: " + filterType);
}
}
// 如果指定了匹配模式
for (final String expression : filterAttributes.getStringArray("pattern")) {
switch (filterType) {
// 过滤类型为 ASPECTJ
case ASPECTJ:
typeFilters.add(new AspectJTypeFilter(expression, resourceLoader.getClassLoader()));
break;
// 过滤类型为 REGEX
case REGEX:
typeFilters.add(new RegexPatternTypeFilter(Pattern.compile(expression)));
break;
default:
throw new IllegalArgumentException("Filter type not supported with String pattern: " + filterType);
}
}
return typeFilters;
}
}
3.3.1.1.3.3 doScan
//ClassPathBeanDefinitionScanner#执行包扫描
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
final Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (final String basePackage : basePackages) {
//根据basePackage加载包下所有java文件,并扫描出所有bean组件,
//findCandidateComponents方法内部调用
//ClassPathScanningCandidateComponentProvider.scanCandidateComponents(backPackages)
final Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
//遍历beandefition
for (final BeanDefinition candidate : candidates) {
//解析作用域Scope
final ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
final String beanName = beanNameGenerator.generateBeanName(candidate, registry);
if (candidate instanceof AbstractBeanDefinition) {
// 应用默认配置
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
//通用注解解析到candidate结构中,主要是处理Lazy, primary DependsOn, Role ,Description这五个注解
if (candidate instanceof AnnotatedBeanDefinition) {
// 处理 BeanDefinition 相关注解
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
//检查当前bean是否已经注册,不存在则注册
if (checkCandidate(beanName, candidate)) {
// 创建 BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
// 尝试应用代理模式
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, registry);
// 添加到 beanDefinitions 进行循环处理
beanDefinitions.add(definitionHolder);
// 注册到ioc容器中,主要是一些@Component组件,@Bean注解方法并没有在此处注册,
// definitionHolder: beanname和beandefinition 键值对
registerBeanDefinition(definitionHolder, registry);
}
}
}
return beanDefinitions;
}
3.3.1.1.3.4 AnnotationConfigUtils
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
processCommonDefinitionAnnotations(abd, abd.getMetadata());
}
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
// 1)目标元素存在 @Lazy 注解
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
else if (abd.getMetadata() != metadata) {
lazy = attributesFor(abd.getMetadata(), Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
}
// 2)目标元素存在 @Primary 注解
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
// 3)目标元素存在 @DependsOn 注解
final AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
if (dependsOn != null) {
abd.setDependsOn(dependsOn.getStringArray("value"));
}
// 4)目标元素存在 @Role 注解
final AnnotationAttributes role = attributesFor(metadata, Role.class);
if (role != null) {
abd.setRole(role.getNumber("value").intValue());
}
// 5)目标元素存在 @Description 注解
final AnnotationAttributes description = attributesFor(metadata, Description.class);
if (description != null) {
abd.setDescription(description.getString("value"));
}
}
static BeanDefinitionHolder applyScopedProxyMode(
ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
// 读取代理模式
final ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
return definition;
}
// 如果是基于 CGLIB 的类代理
final boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
3.3.1.1.3.5 ClassPathScanningCandidateComponentProvider
//扫描指定的类路径
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
if (componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(componentsIndex, basePackage);
}
else {
// 扫描组件
return scanCandidateComponents(basePackage);
}
}
//实现bean定义信息扫描
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
final Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
// @ComponentScan("com.sl.springlearning.extension")包路径处理:
// packageSearchPath = classpath*:com/sl/springlearning/extension/**/*.class
final String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + resourcePattern;
// 通过 ServletContextResourcePatternResolver 读取所有资源(当前包下所有的class文件)
final Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
final boolean traceEnabled = logger.isTraceEnabled();
final boolean debugEnabled = logger.isDebugEnabled();
// 循环处理所有资源
for (final Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
// 资源是可读取的
if (resource.isReadable()) {
try {
// 读取 MetadataReader
final MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
//按照scanner过滤器过滤,比如配置类本身将被过滤掉,没有@Component等组件注解的类将过滤掉
if (isCandidateComponent(metadataReader)) {
// 基于 MetadataReader 创建 ScannedGenericBeanDefinition
final ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
// 是否是候选组件
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
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 (final Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to read candidate component class: " + resource, ex);
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because not readable: " + resource);
}
}
}
}
catch (final IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;
}
/**
* 将类名解析为资源路径
* 为了避免多余的替换操作,可以直接使用 / 作为包分隔符
*/
protected String resolveBasePackage(String basePackage) {
return ClassUtils.convertClassNameToResourcePath(getEnvironment().resolveRequiredPlaceholders(basePackage));
}
/**
* 目标类不匹配任何排除过滤器,并且至少匹配一个包含过滤器
*/
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
for (final TypeFilter tf : excludeFilters) {
// 匹配当期排除过滤器
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
for (final TypeFilter tf : includeFilters) {
// 匹配当前包含过滤器
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
return false;
}
/**
* 目标 BeanDefinition 是否是一个候选组件
*/
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
final AnnotationMetadata metadata = beanDefinition.getMetadata();
/**
* 目标类型不是接口,并且不依赖于封闭类【不是内部类】
*/
return metadata.isIndependent() && (metadata.isConcrete() ||
metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()));
}
3.3.1.1.3.6 ServletContextResourcePatternResolver
/**
* 可配置 ServletContext 的 PathMatchingResourcePatternResolver
*/
public class ServletContextResourcePatternResolver extends PathMatchingResourcePatternResolver {
private static final Log logger = LogFactory.getLog(ServletContextResourcePatternResolver.class);
public ServletContextResourcePatternResolver(ServletContext servletContext) {
super(new ServletContextResourceLoader(servletContext));
}
public ServletContextResourcePatternResolver(ResourceLoader resourceLoader) {
super(resourceLoader);
}
@Override
protected Set<Resource> doFindPathMatchingFileResources(Resource rootDirResource, String subPattern)
throws IOException {
// 如果跟路径资源是 ServletContextResource
if (rootDirResource instanceof ServletContextResource) {
final ServletContextResource scResource = (ServletContextResource) rootDirResource;
final ServletContext sc = scResource.getServletContext();
final String fullPattern = scResource.getPath() + subPattern;
final Set<Resource> result = new LinkedHashSet<>(8);
doRetrieveMatchingServletContextResources(sc, fullPattern, scResource.getPath(), result);
return result;
}
else {
// 默认是 UrlResource
return super.doFindPathMatchingFileResources(rootDirResource, subPattern);
}
}
}
3.3.1.1.3.7 PathMatchingResourcePatternResolver
@Override
public Resource[] getResources(String locationPattern) throws IOException {
Assert.notNull(locationPattern, "Location pattern must not be null");
// 资源路径以 classpath*: 开头
if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
/**
* 支持多个同名文件
* a class path resource (multiple resources for same name possible)
* 资源路径是 Ant 风格的通配符
*/
if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
// a class path resource pattern
return findPathMatchingResources(locationPattern);
}
else {
// 读取 classpath 特定根路径下的所有资源
return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
}
}
else {
// Generally only look for a pattern after a prefix here, and on Tomcat only after the "*/" separator for its "war:" protocol.
final int prefixEnd = locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 :
locationPattern.indexOf(':') + 1;
if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
// a file pattern
return findPathMatchingResources(locationPattern);
}
else {
// a single resource with the given name
return new Resource[] {getResourceLoader().getResource(locationPattern)};
}
}
}
/**
* 通过 Ant 风格的路径匹配器查找所有匹配资源
*/
protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
// 确定给定位置的根目录:classpath*:org/zxd/spring5/
final String rootDirPath = determineRootDir(locationPattern);
// 截取模糊匹配路径:**/*.class
final String subPattern = locationPattern.substring(rootDirPath.length());
// 读取根路径 Resource
final Resource[] rootDirResources = getResources(rootDirPath);
final Set<Resource> result = new LinkedHashSet<>(16);
// 遍历所有根路径
for (Resource rootDirResource : rootDirResources) {
rootDirResource = resolveRootDirResource(rootDirResource);
// 获取根路径 URL
URL rootDirUrl = rootDirResource.getURL();
// 1)URL 协议以 bundle 开头
if (equinoxResolveMethod != null && rootDirUrl.getProtocol().startsWith("bundle")) {
final URL resolvedUrl = (URL) ReflectionUtils.invokeMethod(equinoxResolveMethod, null, rootDirUrl);
if (resolvedUrl != null) {
rootDirUrl = resolvedUrl;
}
rootDirResource = new UrlResource(rootDirUrl);
}
// 2)URL 协议以 vfs 开头
if (rootDirUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirUrl, subPattern, getPathMatcher()));
}
// 3)URL 是一个 jar:jar、war、zip、vfszip、wsjar
else if (ResourceUtils.isJarURL(rootDirUrl) || isJarResource(rootDirResource)) {
result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirUrl, subPattern));
}
else {
// 4)URL 协议以 file 开头
result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
}
}
if (logger.isTraceEnabled()) {
logger.trace("Resolved location pattern [" + locationPattern + "] to resources " + result);
}
return result.toArray(new Resource[0]);
}
protected Resource[] findAllClassPathResources(String location) throws IOException {
String path = location;
if (path.startsWith("/")) {
path = path.substring(1);
}
// 读取所有的 ClassPathResource
final Set<Resource> result = doFindAllClassPathResources(path);
if (logger.isTraceEnabled()) {
logger.trace("Resolved classpath location [" + location + "] to resources " + result);
}
return result.toArray(new Resource[0]);
}
protected Set<Resource> doFindAllClassPathResources(String path) throws IOException {
final Set<Resource> result = new LinkedHashSet<>(16);
// 读取类加载器
final ClassLoader cl = getClassLoader();
// 读取指定包路径【org/zxd/spring5/】下所有资源的 URL
final Enumeration<URL> resourceUrls = cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path);
while (resourceUrls.hasMoreElements()) {
final URL url = resourceUrls.nextElement();
result.add(convertClassLoaderURL(url));
}
if ("".equals(path)) {
// The above result is likely to be incomplete, i.e. only containing file system references.
// We need to have pointers to each of the jar files on the classpath as well...
addAllClassLoaderJarRoots(cl, result);
}
return result;
}
/**
* 将 URL 转换为 UrlResource
*/
protected Resource convertClassLoaderURL(URL url) {
return new UrlResource(url);
}
3.3.1.1.3.8 ConfigurationClassBeanDefinitionReader
配置类 BeanDefinition 读取器
/**
* 从一组完整的 ConfigurationClass 类中解析 BeanDefinition
* 并将其注册到 BeanDefinitionRegistry 中。
*/
class ConfigurationClassBeanDefinitionReader {
private static final Log logger = LogFactory.getLog(ConfigurationClassBeanDefinitionReader.class);
private static final ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
private final BeanDefinitionRegistry registry;
private final SourceExtractor sourceExtractor;
private final ResourceLoader resourceLoader;
private final Environment environment;
private final BeanNameGenerator importBeanNameGenerator;
private final ImportRegistry importRegistry;
private final ConditionEvaluator conditionEvaluator;
/**
* Create a new {@link ConfigurationClassBeanDefinitionReader} instance
* that will be used to populate the given {@link BeanDefinitionRegistry}.
*/
ConfigurationClassBeanDefinitionReader(BeanDefinitionRegistry registry, SourceExtractor sourceExtractor,
ResourceLoader resourceLoader, Environment environment, BeanNameGenerator importBeanNameGenerator,
ImportRegistry importRegistry) {
registry = registry;
sourceExtractor = sourceExtractor;
resourceLoader = resourceLoader;
environment = environment;
importBeanNameGenerator = importBeanNameGenerator;
importRegistry = importRegistry;
conditionEvaluator = new ConditionEvaluator(registry, environment, resourceLoader);
}
/**
* 从已解析的 ConfigurationClass 中读取 BeanDefinition
*/
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
/**
* 读取一个特定的 ConfigurationClass 并注册 BeanDefinition
*/
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
// 是否需要忽略此配置类
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
// 将其从 BeanDefinitionRegistry 中移除
if (StringUtils.hasLength(beanName) && registry.containsBeanDefinition(beanName)) {
registry.removeBeanDefinition(beanName);
}
// 将此类从 importRegistry 中移除
importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
// 1)此配置类是通过 @Import 导入的
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
// 2)处理所有通过 @Bean 注解的方法
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
// 解析通过 @ImportResource 导入的配置文件
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// 解析通过 @Import 导入的 ImportBeanDefinitionRegistrar
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
/**
* 将配置类本身注册到 BeanDefinitionRegistry 中
*/
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
AnnotationMetadata metadata = configClass.getMetadata();
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
String configBeanName = importBeanNameGenerator.generateBeanName(configBeanDef, registry);
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, registry);
registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);
if (logger.isTraceEnabled()) {
logger.trace("Registered bean definition for imported class '" + configBeanName + "'");
}
}
@SuppressWarnings("deprecation") // for RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
ConfigurationClass configClass = beanMethod.getConfigurationClass();
MethodMetadata metadata = beanMethod.getMetadata();
// 读取方法名称
String methodName = metadata.getMethodName();
// 此 Bean 是否已经被忽略
if (configClass.skippedBeanMethods.contains(methodName)) {
return;
}
// 此 Bean 是否需要忽略
if (conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
configClass.skippedBeanMethods.add(methodName);
return;
}
// 读取 @Bean 注解的属性
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
Assert.state(bean != null, "No @Bean annotation attributes");
// 读取 bean 名称
List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
// 如果配置了 bean 名称,则获取第一个;否则以方法名称作为 bean 的名称
String beanName = !names.isEmpty() ? names.remove(0) : methodName;
// 尝试注册别名
for (String alias : names) {
registry.registerAlias(beanName, alias);
}
// Has this effectively been overridden before (e.g. via XML)?
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
"' clashes with bean name for containing configuration class; please make those names unique!");
}
return;
}
// 创建 ConfigurationClassBeanDefinition
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
beanDef.setResource(configClass.getResource());
beanDef.setSource(sourceExtractor.extractSource(metadata, configClass.getResource()));
// @Bean 标注的方法是静态方法
if (metadata.isStatic()) {
// static @Bean method
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
beanDef.setFactoryMethodName(methodName);
}
// @Bean 标注的方法是实例方法
else {
// instance @Bean method
beanDef.setFactoryBeanName(configClass.getBeanName());
beanDef.setUniqueFactoryMethodName(methodName);
}
// 配置属性
beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
// 处理通用 BeanDefinition 注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
// 写入 Autowire
Autowire autowire = bean.getEnum("autowire");
if (autowire.isAutowire()) {
beanDef.setAutowireMode(autowire.value());
}
// 写入 AutowireCandidate
boolean autowireCandidate = bean.getBoolean("autowireCandidate");
if (!autowireCandidate) {
beanDef.setAutowireCandidate(false);
}
// 写入初始化方法
String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
beanDef.setInitMethodName(initMethodName);
}
// 写入销毁方法
String destroyMethodName = bean.getString("destroyMethod");
beanDef.setDestroyMethodName(destroyMethodName);
// Consider scoping
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
if (attributes != null) {
beanDef.setScope(attributes.getString("value"));
proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = ScopedProxyMode.NO;
}
}
// Replace the original bean definition with the target one, if necessary
BeanDefinition beanDefToRegister = beanDef;
if (proxyMode != ScopedProxyMode.NO) {
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
new BeanDefinitionHolder(beanDef, beanName), registry,
proxyMode == ScopedProxyMode.TARGET_CLASS);
beanDefToRegister = new ConfigurationClassBeanDefinition(
(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
}
if (logger.isTraceEnabled()) {
logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
configClass.getMetadata().getClassName(), beanName));
}
// 注册此 BeanDefinition
registry.registerBeanDefinition(beanName, beanDefToRegister);
}
protected boolean isOverriddenByExistingDefinition(BeanMethod beanMethod, String beanName) {
if (!registry.containsBeanDefinition(beanName)) {
return false;
}
BeanDefinition existingBeanDef = registry.getBeanDefinition(beanName);
// Is the existing bean definition one that was created from a configuration class?
// -> allow the current bean method to override, since both are at second-pass level.
// However, if the bean method is an overloaded case on the same configuration class,
// preserve the existing bean definition.
if (existingBeanDef instanceof ConfigurationClassBeanDefinition) {
ConfigurationClassBeanDefinition ccbd = (ConfigurationClassBeanDefinition) existingBeanDef;
return ccbd.getMetadata().getClassName().equals(
beanMethod.getConfigurationClass().getMetadata().getClassName());
}
// A bean definition resulting from a component scan can be silently overridden
// by an @Bean method, as of 4.2...
if (existingBeanDef instanceof ScannedGenericBeanDefinition) {
return false;
}
// Has the existing bean definition bean marked as a framework-generated bean?
// -> allow the current bean method to override it, since it is application-level
if (existingBeanDef.getRole() > BeanDefinition.ROLE_APPLICATION) {
return false;
}
// At this point, it's a top-level override (probably XML), just having been parsed
// before configuration class processing kicks in...
if (registry instanceof DefaultListableBeanFactory &&
!((DefaultListableBeanFactory) registry).isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
beanName, "@Bean definition illegally overridden by existing bean definition: " + existingBeanDef);
}
if (logger.isDebugEnabled()) {
logger.debug(String.format("Skipping bean definition for %s: a definition for bean '%s' " +
"already exists. This top-level bean definition is considered as an override.",
beanMethod, beanName));
}
return true;
}
private void loadBeanDefinitionsFromImportedResources(
Map<String, Class<? extends BeanDefinitionReader>> importedResources) {
Map<Class<?>, BeanDefinitionReader> readerInstanceCache = new HashMap<>();
importedResources.forEach((resource, readerClass) -> {
// 使用默认的 BeanDefinitionReader
if (BeanDefinitionReader.class == readerClass) {
// 目标资源以 .groovy 结尾,则使用 GroovyBeanDefinitionReader 进行读取
if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) {
// When clearly asking for Groovy, that's what they'll get...
readerClass = GroovyBeanDefinitionReader.class;
}
else {
// 否则使用 XmlBeanDefinitionReader 进行读取
readerClass = XmlBeanDefinitionReader.class;
}
}
// 读取缓存的 BeanDefinitionReader
BeanDefinitionReader reader = readerInstanceCache.get(readerClass);
if (reader == null) {
try {
// 实例化特定的 BeanDefinitionReader
reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(registry);
// Delegate the current ResourceLoader to it if possible
if (reader instanceof AbstractBeanDefinitionReader) {
AbstractBeanDefinitionReader abdr = (AbstractBeanDefinitionReader) reader;
abdr.setResourceLoader(resourceLoader);
abdr.setEnvironment(environment);
}
readerInstanceCache.put(readerClass, reader);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Could not instantiate BeanDefinitionReader class [" + readerClass.getName() + "]");
}
}
// 使用 BeanDefinitionReader 读取 BeanDefinition
// TODO SPR-6310: qualify relative path locations as done in AbstractContextLoader.modifyLocations
reader.loadBeanDefinitions(resource);
});
}
/**
* 通过 ImportBeanDefinitionRegistrar 注册 BeanDefinition
*/
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
registrars.forEach((registrar, metadata) ->
registrar.registerBeanDefinitions(metadata, registry));
}
@SuppressWarnings("serial")
private static class ConfigurationClassBeanDefinition extends RootBeanDefinition implements AnnotatedBeanDefinition {
/**
* 注解元数据
*/
private final AnnotationMetadata annotationMetadata;
/**
* 方法元数据
*/
private final MethodMetadata factoryMethodMetadata;
public ConfigurationClassBeanDefinition(ConfigurationClass configClass, MethodMetadata beanMethodMetadata) {
annotationMetadata = configClass.getMetadata();
factoryMethodMetadata = beanMethodMetadata;
setLenientConstructorResolution(false);
}
public ConfigurationClassBeanDefinition(
RootBeanDefinition original, ConfigurationClass configClass, MethodMetadata beanMethodMetadata) {
super(original);
annotationMetadata = configClass.getMetadata();
factoryMethodMetadata = beanMethodMetadata;
}
private ConfigurationClassBeanDefinition(ConfigurationClassBeanDefinition original) {
super(original);
annotationMetadata = original.annotationMetadata;
factoryMethodMetadata = original.factoryMethodMetadata;
}
@Override
public AnnotationMetadata getMetadata() {
return annotationMetadata;
}
@Override
public MethodMetadata getFactoryMethodMetadata() {
return factoryMethodMetadata;
}
@Override
public boolean isFactoryMethod(Method candidate) {
return super.isFactoryMethod(candidate) && BeanAnnotationHelper.isBeanAnnotated(candidate);
}
@Override
public ConfigurationClassBeanDefinition cloneBeanDefinition() {
return new ConfigurationClassBeanDefinition(this);
}
}
private class TrackedConditionEvaluator {
private final Map<ConfigurationClass, Boolean> skipped = new HashMap<>();
public boolean shouldSkip(ConfigurationClass configClass) {
Boolean skip = skipped.get(configClass);
if (skip == null) {
if (configClass.isImported()) {
boolean allSkipped = true;
for (ConfigurationClass importedBy : configClass.getImportedBy()) {
if (!shouldSkip(importedBy)) {
allSkipped = false;
break;
}
}
if (allSkipped) {
// The config classes that imported this one were all skipped, therefore we are skipped...
skip = true;
}
}
if (skip == null) {
skip = conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN);
}
skipped.put(configClass, skip);
}
return skip;
}
}
}
3.3.1.1.4 处理所有的 @Import 注解
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
// 如果配置类上没有任何候选@Import(importCandidates),
//说明没有需要处理的导入,则什么都不用做,直接返回
if (importCandidates.isEmpty()) {
return;
}
// 进行循环依赖的检查
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
// 如果要求做循环导入检查,并且检查到了循环依赖,报告这个问题
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
// 开始处理配置类configClass上所有的@Import importCandidates
this.importStack.push(configClass);
try {
// 循环处理每一个@Import,每个@Import可能导入三种类型的类 :
// 1. ImportSelector
// 2. ImportBeanDefinitionRegistrar
// 3. 其他类型,都当作配置类处理,也就是相当于使用了注解@Configuration的配置类
// 下面的for循环中对这三种情况执行了不同的处理逻辑
for (SourceClass candidate : importCandidates) {
// 目标类是 ImportSelector 实例
if (candidate.isAssignable(ImportSelector.class)) {
Class<?> candidateClass = candidate.loadClass();
// 创建目标实例
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
// 执行 BeanClassLoaderAware、BeanFactoryAware、EnvironmentAware、ResourceLoaderAware 注入
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
// 如果这个类也是DeferredImportSelector接口的实现类,
// 那么加入ConfigurationClassParser的deferredImportSelectors
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
this.deferredImportSelectors.add(
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
}
else {//如果不是,则调用processImports 进行处理.
// 获取所有配置类名称
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
// 获取所有配置类名称
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
// 递归处理所有导入的配置类
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
// 如果这个类是ImportBeanDefinitionRegistrar接口的实现类
// 设置到配置类的importBeanDefinitionRegistrars属性中
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
Class<?> candidateClass = candidate.loadClass();
// 实例化 ImportBeanDefinitionRegistrar
ImportBeanDefinitionRegistrar registrar =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
// 执行 Aware 注入
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
// 写入 importBeanDefinitionRegistrars 缓存
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
//配置类不是 ImportSelector or ImportBeanDefinitionRegistrar,
//则加入到importStack后调用processConfigurationClass 进行处理.
// 其它情况下把这个类入队到ConfigurationClassParser的importStack(队列)属性中
// 然后把这个类当成是@Configuration注解修饰的类递归重头开始解析这个类
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();
}
}
}
3.3.1.1.5 processInterfaces
/**
* 解析接口上的方法,如果此方法存在 @Bean 注解
*/
private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
for (final SourceClass ifc : sourceClass.getInterfaces()) {
final Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
for (final MethodMetadata methodMetadata : beanMethods) {
if (!methodMetadata.isAbstract()) {
// A default method or other concrete method on a Java 8+ interface...
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
}
processInterfaces(configClass, ifc);
}
}
3.3.1.2 ConditionEvaluator条件评估
用于计算 @Conditional 注解的内部类
class ConditionEvaluator {
private final ConditionContextImpl context;
public ConditionEvaluator(@Nullable BeanDefinitionRegistry registry,
@Nullable Environment environment, @Nullable ResourceLoader resourceLoader) {
context = new ConditionContextImpl(registry, environment, resourceLoader);
}
/**
* 指定类或方法上是否存在 @Conditional 注解,并需要跳过处理流程
*/
public boolean shouldSkip(AnnotatedTypeMetadata metadata) {
return shouldSkip(metadata, null);
}
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
// 注解元数据为空 || 目标元素不存在 @Conditional 注解,不跳过
if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
return false;
}
if (phase == null) {
if (metadata instanceof AnnotationMetadata &&
ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
}
return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
}
final List<Condition> conditions = new ArrayList<>();
// 读取所有的条件类
for (final String[] conditionClasses : getConditionClasses(metadata)) {
for (final String conditionClass : conditionClasses) {
final Condition condition = getCondition(conditionClass, context.getClassLoader());
conditions.add(condition);
}
}
// 根据 Order 进行排序
AnnotationAwareOrderComparator.sort(conditions);
for (final Condition condition : conditions) {
ConfigurationPhase requiredPhase = null;
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
// 请求阶段为空或请求阶段==此阶段 && 此条件不匹配
if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(context, metadata)) {
return true;
}
}
// 所有的条件都匹配
return false;
}
@SuppressWarnings("unchecked")
private List<String[]> getConditionClasses(AnnotatedTypeMetadata metadata) {
// 读取所有 @Conditional 注解的属性配置
final MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(Conditional.class.getName(), true);
// 读取评估条件
final Object values = attributes != null ? attributes.get("value") : null;
return (List<String[]>) (values != null ? values : Collections.emptyList());
}
/**
* 实例化目标条件
*/
private Condition getCondition(String conditionClassName, @Nullable ClassLoader classloader) {
final Class<?> conditionClass = ClassUtils.resolveClassName(conditionClassName, classloader);
return (Condition) BeanUtils.instantiateClass(conditionClass);
}
private static class ConditionContextImpl implements ConditionContext {
@Nullable
private final BeanDefinitionRegistry registry;
@Nullable
private final ConfigurableListableBeanFactory beanFactory;
private final Environment environment;
private final ResourceLoader resourceLoader;
@Nullable
private final ClassLoader classLoader;
public ConditionContextImpl(@Nullable BeanDefinitionRegistry registry,
@Nullable Environment environment, @Nullable ResourceLoader resourceLoader) {
this.registry = registry;
beanFactory = deduceBeanFactory(registry);
this.environment = environment != null ? environment : deduceEnvironment(registry);
this.resourceLoader = resourceLoader != null ? resourceLoader : deduceResourceLoader(registry);
classLoader = deduceClassLoader(resourceLoader, beanFactory);
}
@Nullable
private ConfigurableListableBeanFactory deduceBeanFactory(@Nullable BeanDefinitionRegistry source) {
if (source instanceof ConfigurableListableBeanFactory) {
return (ConfigurableListableBeanFactory) source;
}
if (source instanceof ConfigurableApplicationContext) {
return ((ConfigurableApplicationContext) source).getBeanFactory();
}
return null;
}
/**
* 推断 Environment
*/
private Environment deduceEnvironment(@Nullable BeanDefinitionRegistry source) {
if (source instanceof EnvironmentCapable) {
return ((EnvironmentCapable) source).getEnvironment();
}
return new StandardEnvironment();
}
/**
* 推断 ResourceLoader
*/
private ResourceLoader deduceResourceLoader(@Nullable BeanDefinitionRegistry source) {
if (source instanceof ResourceLoader) {
return (ResourceLoader) source;
}
return new DefaultResourceLoader();
}
/**
* 推断 ClassLoader
*/
@Nullable
private ClassLoader deduceClassLoader(@Nullable ResourceLoader resourceLoader,
@Nullable ConfigurableListableBeanFactory beanFactory) {
if (resourceLoader != null) {
final ClassLoader classLoader = resourceLoader.getClassLoader();
if (classLoader != null) {
return classLoader;
}
}
if (beanFactory != null) {
return beanFactory.getBeanClassLoader();
}
return ClassUtils.getDefaultClassLoader();
}
@Override
public BeanDefinitionRegistry getRegistry() {
Assert.state(registry != null, "No BeanDefinitionRegistry available");
return registry;
}
@Override
@Nullable
public ConfigurableListableBeanFactory getBeanFactory() {
return beanFactory;
}
@Override
public Environment getEnvironment() {
return environment;
}
@Override
public ResourceLoader getResourceLoader() {
return resourceLoader;
}
@Override
@Nullable
public ClassLoader getClassLoader() {
return classLoader;
}
}
}
3.3.1.3 ConfigurationClass配置类
ConfigurationClass代表一个配置类,它内部维护了一些已经解析好的但是还没有被加入进Bean定义信息的原始信息,有必要做如下解释:
//它是普通的类,基本只有get set方法
final class ConfigurationClass {
private final AnnotationMetadata metadata;
private final Resource resource;
@Nullable
private String beanName;
private final Set<ConfigurationClass> importedBy = new LinkedHashSet<>(1);
// 存储该配置类里所有标注@Bean注解的方法~~~~
private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();
// 用Map保存着@ImportResource 导入进来的资源们~
private final Map<String, Class<? extends BeanDefinitionReader>> importedResources =
new LinkedHashMap<>();
// 用Map保存着@Import中实现了`ImportBeanDefinitionRegistrar`接口的内容~
private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars =
new LinkedHashMap<>();
final Set<String> skippedBeanMethods = new HashSet<>();
}
3.3.1.4 ConditionalOnProperty
/**
* 此 Environment 中是否存在指定的属性 && 属性具有存在特定值【如果指定】。
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class) // 通过 @Conditional 注解关联条件类
public @interface ConditionalOnProperty {
/**
* 属性的名称
*/
String[] value() default {};
/**
* 每个属性的前缀
*/
String prefix() default "";
/**
* 属性的名称
*/
String[] name() default {};
/**
* 属性值
*/
String havingValue() default "";
/**
* 如果 Environment 中不存在此属性,是否匹配【默认不匹配】
*/
boolean matchIfMissing() default false;
}
/**
* 组件被注册到 BeanDefinitionRegistry 时必须满足的条件
*/
@FunctionalInterface
public interface Condition {
/**
* 判断此条件是否满足
*/
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
public abstract class SpringBootCondition implements Condition {
private final Log logger = LogFactory.getLog(getClass());
@Override
public final boolean matches(ConditionContext context,
AnnotatedTypeMetadata metadata) {
// 读取类名或方法名称
String classOrMethodName = getClassOrMethodName(metadata);
try {
// 读取条件的输出结果
ConditionOutcome outcome = getMatchOutcome(context, metadata);
// 记录日志
logOutcome(classOrMethodName, outcome);
// 记录评估结果
recordEvaluation(context, classOrMethodName, outcome);
// 此条件是否满足
return outcome.isMatch();
}
catch (NoClassDefFoundError ex) {
throw new IllegalStateException(
"Could not evaluate condition on " + classOrMethodName + " due to "
+ ex.getMessage() + " not "
+ "found. Make sure your own configuration does not rely on "
+ "that class. This can also happen if you are "
+ "@ComponentScanning a springframework package (e.g. if you "
+ "put a @ComponentScan in the default package by mistake)",
ex);
}
catch (RuntimeException ex) {
throw new IllegalStateException(
"Error processing condition on " + getName(metadata), ex);
}
}
private String getName(AnnotatedTypeMetadata metadata) {
if (metadata instanceof AnnotationMetadata) {
return ((AnnotationMetadata) metadata).getClassName();
}
if (metadata instanceof MethodMetadata) {
MethodMetadata methodMetadata = (MethodMetadata) metadata;
return methodMetadata.getDeclaringClassName() + "."
+ methodMetadata.getMethodName();
}
return metadata.toString();
}
private static String getClassOrMethodName(AnnotatedTypeMetadata metadata) {
if (metadata instanceof ClassMetadata) {
ClassMetadata classMetadata = (ClassMetadata) metadata;
return classMetadata.getClassName();
}
MethodMetadata methodMetadata = (MethodMetadata) metadata;
return methodMetadata.getDeclaringClassName() + "#"
+ methodMetadata.getMethodName();
}
protected final void logOutcome(String classOrMethodName, ConditionOutcome outcome) {
if (this.logger.isTraceEnabled()) {
this.logger.trace(getLogMessage(classOrMethodName, outcome));
}
}
private StringBuilder getLogMessage(String classOrMethodName,
ConditionOutcome outcome) {
StringBuilder message = new StringBuilder();
message.append("Condition ");
message.append(ClassUtils.getShortName(getClass()));
message.append(" on ");
message.append(classOrMethodName);
message.append(outcome.isMatch() ? " matched" : " did not match");
if (StringUtils.hasLength(outcome.getMessage())) {
message.append(" due to ");
message.append(outcome.getMessage());
}
return message;
}
private void recordEvaluation(ConditionContext context, String classOrMethodName,
ConditionOutcome outcome) {
if (context.getBeanFactory() != null) {
ConditionEvaluationReport.get(context.getBeanFactory())
.recordConditionEvaluation(classOrMethodName, this, outcome);
}
}
/**
* 确定匹配结果
*/
public abstract ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata);
/**
* 只要有一个条件满足
*/
protected final boolean anyMatches(ConditionContext context,
AnnotatedTypeMetadata metadata, Condition... conditions) {
for (Condition condition : conditions) {
if (matches(context, metadata, condition)) {
return true;
}
}
return false;
}
/**
* 指定的条件是否满足
*/
protected final boolean matches(ConditionContext context,
AnnotatedTypeMetadata metadata, Condition condition) {
if (condition instanceof SpringBootCondition) {
return ((SpringBootCondition) condition).getMatchOutcome(context, metadata)
.isMatch();
}
return condition.matches(context, metadata);
}
}
/**
* 指定的属性是否定义在此 Environment 中
*/
@Order(Ordered.HIGHEST_PRECEDENCE + 40)
class OnPropertyCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 读取目标元素上所有的 @ConditionalOnProperty 注解的属性信息
final List<AnnotationAttributes> allAnnotationAttributes = annotationAttributesFromMultiValueMap(
metadata.getAllAnnotationAttributes(ConditionalOnProperty.class.getName()));
final List<ConditionMessage> noMatch = new ArrayList<>();
final List<ConditionMessage> match = new ArrayList<>();
for (final AnnotationAttributes annotationAttributes : allAnnotationAttributes) {
// 确定当前 ConditionalOnProperty 条件的输出结果
final ConditionOutcome outcome = determineOutcome(annotationAttributes, context.getEnvironment());
// 记录 ConditionMessage
(outcome.isMatch() ? match : noMatch).add(outcome.getConditionMessage());
}
// 存在一个不匹配条件
if (!noMatch.isEmpty()) {
return ConditionOutcome.noMatch(ConditionMessage.of(noMatch));
}
// 所有的条件都匹配
return ConditionOutcome.match(ConditionMessage.of(match));
}
private List<AnnotationAttributes> annotationAttributesFromMultiValueMap(
MultiValueMap<String, Object> multiValueMap) {
final List<Map<String, Object>> maps = new ArrayList<>();
multiValueMap.forEach((key, value) -> {
for (int i = 0; i < value.size(); i++) {
Map<String, Object> map;
if (i < maps.size()) {
map = maps.get(i);
} else {
map = new HashMap<>();
maps.add(map);
}
map.put(key, value.get(i));
}
});
final List<AnnotationAttributes> annotationAttributes = new ArrayList<>(maps.size());
for (final Map<String, Object> map : maps) {
annotationAttributes.add(AnnotationAttributes.fromMap(map));
}
return annotationAttributes;
}
private ConditionOutcome determineOutcome(AnnotationAttributes annotationAttributes, PropertyResolver resolver) {
final Spec spec = new Spec(annotationAttributes);
final List<String> missingProperties = new ArrayList<>();
final List<String> nonMatchingProperties = new ArrayList<>();
spec.collectProperties(resolver, missingProperties, nonMatchingProperties);
// 1)属性值不存在
if (!missingProperties.isEmpty()) {
return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnProperty.class, spec)
.didNotFind("property", "properties").items(Style.QUOTE, missingProperties));
}
// 2)属性值存在,但是不匹配
if (!nonMatchingProperties.isEmpty()) {
return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnProperty.class, spec)
.found("different value in property", "different value in properties")
.items(Style.QUOTE, nonMatchingProperties));
}
// 此 ConditionalOnProperty 条件匹配
return ConditionOutcome
.match(ConditionMessage.forCondition(ConditionalOnProperty.class, spec).because("matched"));
}
private static class Spec {
private final String prefix;
private final String havingValue;
private final String[] names;
private final boolean matchIfMissing;
Spec(AnnotationAttributes annotationAttributes) {
// 读取 ConditionalOnProperty 注解的 prefix 属性
String prefix = annotationAttributes.getString("prefix").trim();
// prefix 不为空,则尝试添加 . 后缀
if (StringUtils.hasText(prefix) && !prefix.endsWith(".")) {
prefix = prefix + ".";
}
this.prefix = prefix;
// 读取 ConditionalOnProperty 注解的 havingValue 属性
havingValue = annotationAttributes.getString("havingValue");
// 读取 ConditionalOnProperty 注解的关联属性名称
names = getNames(annotationAttributes);
// 读取 ConditionalOnProperty 注解的 matchIfMissing 属性
matchIfMissing = annotationAttributes.getBoolean("matchIfMissing");
}
private String[] getNames(Map<String, Object> annotationAttributes) {
final String[] value = (String[]) annotationAttributes.get("value");
final String[] name = (String[]) annotationAttributes.get("name");
Assert.state(value.length > 0 || name.length > 0,
"The name or value attribute of @ConditionalOnProperty must be specified");
Assert.state(value.length == 0 || name.length == 0,
"The name and value attributes of @ConditionalOnProperty are exclusive");
// value 属性的优先级高于 name
return value.length > 0 ? value : name;
}
private void collectProperties(PropertyResolver resolver, List<String> missing, List<String> nonMatching) {
// 遍历所有的属性名称
for (final String name : names) {
// 添加前缀
final String key = prefix + name;
// 1)如果 Environment 中存在此属性
if (resolver.containsProperty(key)) {
// 指定的值不匹配,则写入 nonMatching 中
if (!isMatch(resolver.getProperty(key), havingValue)) {
nonMatching.add(name);
}
// 2)Environment 中不存在此属性
} else {
// 如果不能忽略此属性,则写入 missing 中
if (!matchIfMissing) {
missing.add(name);
}
}
}
}
private boolean isMatch(String value, String requiredValue) {
// 1)指定了必须的值,则使用 equals 进行比较
if (StringUtils.hasLength(requiredValue)) {
return requiredValue.equalsIgnoreCase(value);
}
// 只要属性值不是忽略大小写的 false,就匹配
return !"false".equalsIgnoreCase(value);
}
@Override
public String toString() {
final StringBuilder result = new StringBuilder();
result.append("(");
result.append(prefix);
if (names.length == 1) {
result.append(names[0]);
} else {
result.append("[");
result.append(StringUtils.arrayToCommaDelimitedString(names));
result.append("]");
}
if (StringUtils.hasLength(havingValue)) {
result.append("=").append(havingValue);
}
result.append(")");
return result.toString();
}
}
}
3.4 loadBeanDefinitions加载bean定义信息
ConfigurationClassBeanDefinitionReader.loadBeanDefinitions()方法的功能就是将之前解析出的configClasses配置类信息中所有配置相关的信息添加到spring的bean定义,主要是配置类中的@Bean注解方法,配置类@ImportResource和@Import(实现ImportBeanDefinitionRegistrar接口方式)的bean注册
ConfigurationClassBeanDefinitionReader.loadBeanDefinitions()方法 实现逻辑如下:
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;
}
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//将@Bean方法注册为bean
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
//将configClass中中ImportResource指定的资源注册为bean
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
//将configClass中ImportedRegistrar注册为bean
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
处理逻辑理了一遍后,看一下ConfigurationClassPostProcessor处理器解析@configuration配置类主要过程:
1. Spring容器初始化时注册默认后置处理器ConfigurationClassPostProcessor
2. Spring容器初始化执行refresh()方法中调用ConfigurationClassPostProcessor
3. ConfigurationClassPostProcessor处理器借助ConfigurationClassParser完成配置类解析
4. ConfigurationClassParser配置内解析过程中完成嵌套的MemberClass、@PropertySource注解、@ComponentScan注解(扫描package下的所有Class并进行迭代解析,主要是@Component组件解析及注册)、@ImportResource、@Bean等处理
5. 完成@Bean注册, @ImportResource指定bean的注册以及@Import(实现ImportBeanDefinitionRegistrar接口方式)的bean注册
4 总结
扫描Bean的顺序(并不是Bean定义真正注册的顺序):
- 内部配置类:–> 它里面还可以有普通配置类一模一样的功能,但优先级最高,最终会放在configurationClasses这个Map的第一位
- @PropertySource:这个和Bean定义没啥关系,属于Spring配置PropertySource的范畴。这个属性优先级相对较低
- @ComponentScan:这里扫描到的Bean定义,就直接register注册了。所以它的时机是非常早的。(另外:如果注册进去的Bean定义信息还是配置类,这里会继续parse(),所以最终能被扫描到的组件,最终都会当作一个配置类来处理,所以最终都会放进configurationClasses这个Map里面去)
-
@Import:相对复杂点,如下:
- 若是一个普通类(标注@Configuration与否都无所谓反正会当作一个配置类来处理,也会放进configurationClasses缓存进去)
- 实现了ImportSelector:递归最后都成为第一步的类。若实现的是DeferredImportSelector接口,它会放在deferredImportSelectors属性里先保存着,等着外部所有的configCandidates配置类全部解析完成后,统一processDeferredImportSelectors(),最终也是转为第一步的类。
- 实现了ImportBeanDefinitionRegistrar:放在ConfigurationClass.importBeanDefinitionRegistrars属性里保存着
- @ImportResource:一般用来导入xml文件。它是先放在ConfigurationClass.importedResources属性里放着
- @Bean:找到所有@Bean的方法,然后保存到ConfigurationClass.beanMethods属性里
- processInterfaces:处理该类实现的接口们的default方法(标注@Bean的有效)
- 处理父类:拿到父类,每个父类都是当作一个配置文件来处理。备注:!superclass.startsWith("java")全类名不以java打头,且没有被处理过(因为一个父类可以有N个子类,但只能被处理一次)
- return null:若全部处理完成后就返回null,停止递归。
由上可见,这九步中,唯独只有@ComponentScan扫描到的Bean这个时候的Bean定义信息是已经注册上去了的,其余的都还没有真正注册到注册中心。
注意:bean注册的先后顺序,将直接影响到Bean的覆盖(默认Map,后注册的覆盖先注册的,当然还和scope有关)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。