AnnotationConfigApplicationContext
使用AnnotationConfigApplicationContext可以实现基于Java的配置类(包括各种注解)加载Spring的应用上下文。避免使用application.xml进行配置。相比XML配置,更加便捷。
一、被@Configuration标记的Bean的资源定位、加载、解析、注册分析
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Xxx.class);
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
//保存一个读取注解的Bean 定义读取器,并将其设置到容器中
private final AnnotatedBeanDefinitionReader reader;
//保存一个扫描指定类路径中注解Bean 定义的扫描器,并将其设置到容器中
private final ClassPathBeanDefinitionScanner scanner;
/**
* 默认构造函数,初始化一个空容器,容器不包含任何Bean 信息,需要在稍后通过调用其register()
* 方法注册配置类,并调用refresh()方法刷新容器,触发容器对注解Bean 的载入、解析和注册过程
* Create a new AnnotationConfigApplicationContext that needs to be populated
* through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
*/
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public AnnotationConfigApplicationContext(Class>... componentClasses) {
//调用默认无参构造器,主要初始化AnnotatedBeanDefinitionReader
// 以及路径扫描器ClassPathBeanDefinitionScanner
this();
//把传入的Class进行注册,Class既可以有@Configuration注解,也可以没有@Configuration注解
//如何注册委托给了 org.springframework.context.annotation.AnnotatedBeanDefinitionReader.register 方法进行注册
// 包装传入的Class 生成 BeanDefinition , 注册到BeanDefinitionRegistry
register(componentClasses);
refresh();
}
@Override
public void register(Class>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
this.reader.register(componentClasses);
}
}
AnnotatedBeanDefinitionReader
发现 AnnotatedBeanDefinitionReader没有继承和实现任何类与接口,即该类并不属于BeanDefinitionReader的体系,而是专门用于处理注解相关的BeanDefinition的配置读入,这样做可以用于区分出注解和其他配置方式的不同。
注解的处理逻辑相对更清晰,在上一文分析了XML相关的解析逻辑之后,理解注解也会相对容易一些。
深入this.reader.register(componentClasses)方法,进入AnnotatedBeanDefinitionReader类
public class AnnotatedBeanDefinitionReader {
//还是委托BeanDefinitionRegistry将AnnotatedBeanDefinition实例注入到IOC容器中
private final BeanDefinitionRegistry registry;
public void register(Class>... componentClasses) {
for (Class> componentClass : componentClasses) {
registerBean(componentClass);
}
}
public void registerBean(Class> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}
}
doRegisterBean()方法真正的注册方法,继续深入
public class AnnotatedBeanDefinitionReader {
private void doRegisterBean(Class beanClass, @Nullable String name,
@Nullable Class extends Annotation>[] qualifiers, @Nullable Supplier supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
//此段代码用于处理 Conditional 注解,在特定条件下阻断 bean 的注册
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
//用来创建 bean 的 supplier,会替代掉 bean 本身的创建方法
//instanceSupplier 一般情况下为 null
abd.setInstanceSupplier(supplier);
//此行代码处理 scope 注解,本例中 scope 是默认值 singleton
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
//获取beanName
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//特定注解解析,本例中均没传入dependsOn,LazyInit这些注解
//这些注解就和标签里面的属性作用是一样的
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
//本例中 qualifiers 传入的是 null,qualifiers就是用来决定接口的实现类的
if (qualifiers != null) {
for (Class extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
//主要提供对BeanDefinition的一些定制化操作
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
//用 BeanDefinitionHolder 包装 BeanDefinition
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
//此行代码与动态代理和 scope 注解有关,主要看看是否依照Spring的scope生成动态代理对象
// 但是在本案例中没有做任何操作,只是返回了传入的 definitionHolder
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//向容器注册扫描到的Bean
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
- 1、将类转换为AnnotatedGenericBeanDefinition。
- 2、调用conditionEvaluator的shouldSkip判断是否需要过滤,shouldSkip方法中先判断类上是否有Conditional注解,只处理有Conditional注解或其衍生注解的情况。
- 3、获取beanName,如果我们设置了value则取其值,如果没有设置,底层上是调用JDK的Introspector.decapitalize方法,比如类名是HelloWorld,则对应的beanName是helloWorld。
- 4、调用AnnotationConfigUtils.processCommonDefinitionAnnotations,获取Lazy、Primary、DependsOn等注解的值。
- 5、最后调用BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry)将这个BeanDefinition注册到registry中,这里的注册和xml方式的注册一模一样。
使用AnnotationConfigUtils的processCommonDefinitionAnnotations方法处理注解Bean定义类中通用的注解
二、不是被@Configuration标记的Bean(即普通的业务Bean)的资源定位、加载、解析、注册分析
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
public AnnotationConfigApplicationContext(Class>... componentClasses) {
//调用默认无参构造器,主要初始化AnnotatedBeanDefinitionReader
// 以及路径扫描器ClassPathBeanDefinitionScanner
this();
//把传入的Class进行注册,Class既可以有@Configuration注解,也可以没有@Configuration注解
//如何注册委托给了 org.springframework.context.annotation.AnnotatedBeanDefinitionReader.register 方法进行注册
// 包装传入的Class 生成 BeanDefinition , 注册到BeanDefinitionRegistry
register(componentClasses);
//@Controller、@Service、@Component、@Repository标记的类在此方法被注册进IOC容器
refresh();
}
}
针对普通的业务Bean,即@Controller、@Service、@Component、@Repository标记的类是在AnnotationConfigApplicationContext构造函数中的refresh()方法的时候才会被注册进IOC容器,这和XML解析方式一样是调用的AbstractApplicationContext中的refresh()方法。
- XML配置方式的解析配置并注册BeanDefinition实例时候,是调用的obtainFreshBeanFactory()方法。
- 而注解方式是调用的invokeBeanFactoryPostProcessors(beanFactory)方法,在容器调用其后置处理器的时候会触发对普通的BeanDefinition的注册。
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
/**
* 加载或刷新一个持久化的配置,可能是XML文件、属性文件或关系数据库模式。
* 由于这是一种启动方法,如果失败,应该销毁已经创建的单例,以避免悬空资源。
* 换句话说,在调用该方法之后,要么全部实例化,要么完全不实例化。
* @throws BeansException 如果bean工厂无法初始化,则抛出 BeansException 异常
* @throws IllegalStateException 如果已经初始化且不支持多次刷新,则会抛出 IllegalStateException 异常
*/
@Override
public void refresh() throws BeansException, IllegalStateException {
// 给容器refresh加锁,避免容器处在refresh阶段时,容器进行了初始化或者销毁的操作
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识,具体方法
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
//子类的refreshBeanFactory()方法启动,里面有抽象方法
//针对xml配置,最终创建内部容器,该容器负责 Bean 的创建与管理,此步会进行BeanDefinition的注册
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 注册一些容器中需要的系统Bean.例如classloader,beanfactoryPostProcessor等
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//允许容器的子类去注册postProcessor ,钩子方法
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 激活在容器中注册为bean的BeanFactoryPostProcessors
//对于注解容器,org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
//方法扫描应用中所有BeanDefinition并注册到容器之中
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册拦截bean创建过程的BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 找到“messageSource”的Bean提供给ApplicationContext使用,
// 使得ApplicationContext具有国际化能力。
initMessageSource();
// Initialize event multicaster for this context.
// 初始化ApplicationEventMulticaster该类作为事件发布者,
// 可以存储所有事件监听者信息,并根据不同的事件,通知不同的事件监听者。
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 预留给 AbstractApplicationContext 的子类用于初始化其他特殊的 bean,
// 该方法需要在所有单例 bean 初始化之前调用
// 比如Web容器就会去初始化一些和主题展示相关的Bean(ThemeSource)
onRefresh();
// Check for listener beans and register them.
// 注册监听器(检查监听器的bean并注册它们)
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//设置自定义的类型转化器ConversionService,
// 设置自定义AOP相关的类LoadTimeWeaverAware,
// 清除临时的ClassLoader
// ,实例化所有的类(懒加载的类除外)
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 初始化容器的生命周期事件处理器,(默认使用DefaultLifecycleProcessor),调用扩展了SmartLifecycle接口的start方法
// 当Spring容器加载所有bean并完成初始化之后,会接着回调实现该接口的类中对应的方法(start()方法)
// 并发布容器刷新完毕事件ContextRefreshedEvent给对应的事件监听者
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
//销毁已创建的Bean
destroyBeans();
// Reset 'active' flag.
//取消refresh操作,重置容器的同步标识
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
// 重置Spring内核中的共用的缓存,因为我们可能再也不需要单例bean的元数据了……
resetCommonCaches();
}
}
}
}
invokeBeanFactoryPostProcessors(beanFactory)方法中
- 该方法会实例化和调用所有 BeanFactoryPostProcessor(包括其子类 BeanDefinitionRegistryPostProcessor)。
- BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。
- BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的优先级,主要用来在常规的 BeanFactoryPostProcessor 检测开始之前注册其他 bean 定义。特别是,你可以通过 BeanDefinitionRegistryPostProcessor 来注册一些常规的 BeanFactoryPostProcessor,因为此时所有常规的 BeanFactoryPostProcessor 都还没开始被处理。
注:这边的 “常规 BeanFactoryPostProcessor” 主要用来跟 BeanDefinitionRegistryPostProcessor 区分。
接着深入invokeBeanFactoryPostProcessors(beanFactory)方法
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
/**
* 实例化并调用所有已注册的BeanFactoryPostProcessor 的 bean,如果已给出顺序,请按照顺序。
* 必须在单实例实例化之前调用。
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* Must be called before singleton instantiation.
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 1.getBeanFactoryPostProcessors(): 拿到当前应用上下文beanFactoryPostProcessors变量中的值
// 2.invokeBeanFactoryPostProcessors: 实例化并调用所有已注册的BeanFactoryPostProcessor
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// 如何找到一个LoadTimeWeaver,那么就准备将后置处理器“织入”bean工厂
// (例如,一个 @Bean 方法通过ConfigurationClassPostProcessor来注册)
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
}
1、拿到当前应用上下文 beanFactoryPostProcessors 变量中的值。
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
//应用于刷新的 BeanFactoryPostProcessors,这个List用于存放Bean工厂处理器(BeanFactoryPostProcessor)
private final List beanFactoryPostProcessors = new ArrayList<>();
//返回将应用到内部BeanFactory的BeanFactoryPostProcessors列表
public List getBeanFactoryPostProcessors() {
return this.beanFactoryPostProcessors;
}
}
这边 getBeanFactoryPostProcessors() 会拿到当前应用上下文中已经注册的 BeanFactoryPostProcessor,在默认情况下,this.beanFactoryPostProcessors 是返回空的。
如何添加自定义 BeanFactoryPostProcessor 到 this.beanFactoryPostProcessors 变量中?
新建一个 ApplicationContextInitializer 的实现类 SpringApplicationContextInitializer ,并在 initialize 方法中写我们的逻辑。
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
FirstBeanDefinitionRegistryPostProcessor firstBeanDefinitionRegistryPostProcessor = new FirstBeanDefinitionRegistryPostProcessor();
// 将自定义的firstBeanDefinitionRegistryPostProcessor添加到应用上下文中
applicationContext.addBeanFactoryPostProcessor(firstBeanDefinitionRegistryPostProcessor);
// ...自定义操作
System.out.println("MyApplicationContextInitializer#initialize");
}
}
1、Spring实现方式
将 SpringApplicationContextInitializer 作为初始化参数 contextInitializerClasses 配置到 web.xml 中。
contextInitializerClasses
com.yibo.spring.MyApplicationContextInitializer
这样,在启动应用时,FirstBeanDefinitionRegistryPostProcessor 就会被添加到 this.beanFactoryPostProcessors 中。
2、SpringBoot方式
2.1、mian函数中添加
@SpringBootApplication
public class MySpringBootApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MySpringBootApplication.class);
application.addInitializers(new MyApplicationContextInitializer());
application.run(args);
}
}
2.2、配置文件中配置
context.initializer.classes= com.yibo.spring.MyApplicationContextInitializer
2.3、SpringBoot的SPI扩展---META-INF/spring.factories中配置
在项目下的resources下新建META-INF文件夹,文件夹下新建spring.factories文件
org.springframework.context.ApplicationContextInitializer= com.yibo.spring.MyApplicationContextInitializer
给 MyApplicationContextInitializer 加上Order注解:我们指定其拥有最高的排序级别。(越高越早执行)
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
FirstBeanDefinitionRegistryPostProcessor firstBeanDefinitionRegistryPostProcessor = new FirstBeanDefinitionRegistryPostProcessor();
// 将自定义的firstBeanDefinitionRegistryPostProcessor添加到应用上下文中
applicationContext.addBeanFactoryPostProcessor(firstBeanDefinitionRegistryPostProcessor);
// ...自定义操作
System.out.println("MyApplicationContextInitializer#initialize");
}
}
2、实例化并调用所有已注册的 BeanFactoryPostProcessor
深入PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
final class PostProcessorRegistrationDelegate {
/**
* 调用BeanFactoryPostProcessor
* 主要是分情况处理不同类型的BeanFactoryPostProcessors。
* BeanFacotryPostProcessors主要分为两类,一类是BeanDefinitionRegistry的BeanFactoryPostProcessor,另外一类是常规的BeanFactoryPostProcessor。
* 优先处理前者。同时,这两种后置处理器又被分为从参数里传入和从容器里获取的,最终要将从参数里获取的和从容器里获取的合并在一起。
* 合并的时候又分为实现了PriorityOrder和普通Order以及没有实现这两个接口的,实现了PriorityOrdered的先执行,
* 同时是按照PriorityOrdered顺序执行的,其次再到Order,按照Order执行,最后才是没实现这两个接口的,
* 先执行完BeanDefinitionRegistryPostProcessor的invokeBeanDefinitionRegistryPostProcessors方法,
* 再对BeanDefinitionRegistryPostProcessor执行invokeBeanFactoryPostProcessors方法,
* 之后再对常规的BeanFacotryPostProcessors执行invokeBeanFactoryPostProcessors方法
* @参数 beanFactory 应用上下文的 BeanFactory 实例
* @参数 beanFactoryPostProcessors 应用上下文指定要执行的 BeanFactoryPostProcessor
**/
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
// 如果有BeanDefinitionRegistryPostProcessor的话优先执行
Set processedBeans = new HashSet<>();
// 1.判断beanFactory是否为BeanDefinitionRegistry,beanFactory为DefaultListableBeanFactory,
// 而DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,因此这边为true
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 用于存放普通的BeanFactoryPostProcessor
List regularPostProcessors = new ArrayList<>();
// 用于存放BeanDefinitionRegistryPostProcessor
List registryProcessors = new ArrayList<>();
// 2.首先处理入参中的beanFactoryPostProcessors
// 遍历所有的beanFactoryPostProcessors, 将BeanDefinitionRegistryPostProcessor和普通BeanFactoryPostProcessor区分开
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
// 2.1 如果是BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
// 2.1.1 直接执行BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法
registryProcessor.postProcessBeanDefinitionRegistry(registry);
// 2.1.2 添加到registryProcessors(用于最后执行postProcessBeanFactory方法)
registryProcessors.add(registryProcessor);
}
else {
// 2.2 否则,只是普通的BeanFactoryPostProcessor
// 2.2.1 添加到regularPostProcessors(用于最后执行postProcessBeanFactory方法)
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
// 用于保存本次要执行的BeanDefinitionRegistryPostProcessor
List currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 3.调用所有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类
// 3.1 找出所有实现BeanDefinitionRegistryPostProcessor接口的Bean的beanName
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 3.2 遍历postProcessorNames
for (String ppName : postProcessorNames) {
// 3.3 校验是否实现了PriorityOrdered接口
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 3.4 获取ppName对应的bean实例, 添加到currentRegistryProcessors中,
// beanFactory.getBean: 这边getBean方法会触发创建ppName对应的bean对象, 目前暂不深入解析
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 3.5 将要被执行的加入processedBeans,避免后续重复执行
processedBeans.add(ppName);
}
}
// 3.6 进行排序(根据是否实现PriorityOrdered、Ordered接口和order值来排序)
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 3.7 添加到registryProcessors(用于最后执行postProcessBeanFactory方法)
registryProcessors.addAll(currentRegistryProcessors);
// 3.8 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 3.9 执行完毕后, 清空currentRegistryProcessors
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// 4.调用所有实现了Ordered接口的BeanDefinitionRegistryPostProcessor实现类(过程跟上面的步骤3基本一样)
// 4.1 找出所有实现BeanDefinitionRegistryPostProcessor接口的类, 这边重复查找是因为执行完上面的BeanDefinitionRegistryPostProcessor,
// 可能会新增了其他的BeanDefinitionRegistryPostProcessor, 因此需要重新查找
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 校验是否实现了Ordered接口,并且还未执行过
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 4.2 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// 5.最后, 调用所有剩下的BeanDefinitionRegistryPostProcessors
boolean reiterate = true;
while (reiterate) {
reiterate = false;
// 5.1 找出所有实现BeanDefinitionRegistryPostProcessor接口的类
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 5.2 跳过已经执行过的
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
// 5.3 如果有BeanDefinitionRegistryPostProcessor被执行, 则有可能会产生新的BeanDefinitionRegistryPostProcessor,
// 因此这边将reiterate赋值为true, 代表需要再循环查找一次
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 5.4 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 6.调用所有BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法(BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor)
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 7.最后, 调用入参beanFactoryPostProcessors中的普通BeanFactoryPostProcessor的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// 到这里 , 入参beanFactoryPostProcessors和容器中的所有BeanDefinitionRegistryPostProcessor已经全部处理完毕,
// 下面开始处理容器中的所有BeanFactoryPostProcessor
// 8.找出所有实现BeanFactoryPostProcessor接口的类
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 用于存放实现了PriorityOrdered接口的BeanFactoryPostProcessor
List priorityOrderedPostProcessors = new ArrayList<>();
// 用于存放实现了Ordered接口的BeanFactoryPostProcessor的beanName
List orderedPostProcessorNames = new ArrayList<>();
// 用于存放普通BeanFactoryPostProcessor的beanName
List nonOrderedPostProcessorNames = new ArrayList<>();
// 8.1 遍历postProcessorNames, 将BeanFactoryPostProcessor按实现PriorityOrdered、实现Ordered接口、普通三种区分开
for (String ppName : postProcessorNames) {
// 8.2 跳过已经执行过的
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 8.3 添加实现了PriorityOrdered接口的BeanFactoryPostProcessor
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
// 8.4 添加实现了Ordered接口的BeanFactoryPostProcessor的beanName
orderedPostProcessorNames.add(ppName);
}
else {
// 8.5 添加剩下的普通BeanFactoryPostProcessor的beanName
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
// 9.调用所有实现PriorityOrdered接口的BeanFactoryPostProcessor
// 9.1 对priorityOrderedPostProcessors排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 9.2 遍历priorityOrderedPostProcessors, 执行postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
// 10.调用所有实现Ordered接口的BeanFactoryPostProcessor
List orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
// 10.1 获取postProcessorName对应的bean实例, 添加到orderedPostProcessors, 准备执行
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
// 10.2 对orderedPostProcessors排序
sortPostProcessors(orderedPostProcessors, beanFactory);
// 10.3 遍历orderedPostProcessors, 执行postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
// 11.调用所有剩下的BeanFactoryPostProcessor
List nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
// 11.1 获取postProcessorName对应的bean实例, 添加到nonOrderedPostProcessors, 准备执行
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
// 11.2 遍历nonOrderedPostProcessors, 执行postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
// 12.清除元数据缓存(mergedBeanDefinitions、allBeanNamesByType、singletonBeanNamesByType),
// 因为后处理器可能已经修改了原始元数据,例如, 替换值中的占位符...
beanFactory.clearMetadataCache();
}
}
调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)进行BeanDefinition的注册
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
上一步每一个BeanDefinitionRegistryPostProcessor都会调用postProcessBeanDefinitionRegistry(registry)进行处理,继续深入该方法
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
}
通过上面发现,BeanDefinition实例的注册是通过ConfigurationClassPostProcessor类的后置处理方法processConfigBeanDefinitions(registry);方法来处理。
继续深入processConfigBeanDefinitions(registry)方法
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
//1.初始化BeanDefinitionHolder集合
List configCandidates = new ArrayList<>();
//2.所有已经注册的bean
String[] candidateNames = registry.getBeanDefinitionNames();
//3.遍历已注册的bean数组
for (String beanName : candidateNames) {
//得到BeanDefinition实例
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
//如果BeanDefinition 中的configurationClass 属性为full 或者lite ,则意味着已经处理过了,直接跳过
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
//带有@Configuration注解的bean添加到集合中
// 判断对应bean是否为配置类,如果是,则加入到configCandidates
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
// 对configCandidates 进行 排序,按照@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
// 如果BeanDefinitionRegistry 是SingletonBeanRegistry 的子类的话,
// 由于我们当前传入的是DefaultListableBeanFactory,它是
// SingletonBeanRegistry 的子类。因此会将registry强转为SingletonBeanRegistry
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
//web应用为StandardServletEnvironment
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
//初始化一个ConfigurationClassParser解析器,可以解析@Congiguration配置类
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
//List转成Set
Set candidates = new LinkedHashSet<>(configCandidates);
//初始化一个已经解析的HashSet
Set alreadyParsed = new HashSet<>(configCandidates.size());
//循环解析,直到candidates为空
do {
//核心:解析
parser.parse(candidates);
//主要校验配置类不能使用final修饰符(CGLIB代理是生成一个子类,因此原先的类不能使用final修饰)
//if (this.getMetadata().isAnnotated(Configuration.class.getName()) && this.getMetadata().isFinal())
parser.validate();
//排除已处理过的配置类
Set configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
//读取模型并根据其内容创建bean定义
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
//2.加载bean定义信息,主要实现将@Configuration @Import @ImportResource @ImportRegistrar注册为bean
this.reader.loadBeanDefinitions(configClasses);
//将configClasses加入到已解析alreadyParsed中
alreadyParsed.addAll(configClasses);
//清空已处理的配置类
candidates.clear();
//再次获取容器中bean定义数量 如果大于 之前获取的bean定义数量,则说明有新的bean注册到容器中,需要再次解析
//getBeanDefinitionCount()取得是registry.beanDefinitionMap.size()
if (registry.getBeanDefinitionCount() > candidateNames.length) {
//容器中新的所有已注册的bean(包括老的)
String[] newCandidateNames = registry.getBeanDefinitionNames();
//容器中老的已注册的bean(已经解析了)
Set oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
//用来存储已经解析的类
Set alreadyParsedClasses = new HashSet<>();
//循环遍历把已解析的类放到alreadyParsedClasses中
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
//循环遍历新的所有已注册的bean,排除老的已解析的,再过滤是否是配置类带有@Configuration,并且没有解析过,添加到candidates中,
//下一次可以再处理解析
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();
}
}
}
parser.parse(candidates)对配置类的解析
class ConfigurationClassParser {
private final DeferredImportSelectorHandler deferredImportSelectorHandler = new DeferredImportSelectorHandler();
public void parse(Set configCandidates) {
//循环遍历需要处理的配置类
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
//根据BeanDefinition实例判断调用哪个,其实最后还是调用
//核心方法:processConfigurationClass(ConfigurationClass configClass)
try {
if (bd instanceof AnnotatedBeanDefinition) {
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);
}
}
//字面理解:处理延迟导入的javabean
//parse方法,把被处理的类实现DeferredImportSelector接口,加入deferredImportSelectors集合中,
//处理deferredImportSelectors集合种类
this.deferredImportSelectorHandler.process();
}
}
继续深入其中的一个parse()方法
class ConfigurationClassParser {
protected final void parse(@Nullable String className, String beanName) throws IOException {
Assert.notNull(className, "No bean class name for configuration class bean definition");
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
processConfigurationClass(new ConfigurationClass(reader, beanName), DEFAULT_EXCLUSION_FILTER);
}
protected final void parse(Class> clazz, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(clazz, beanName), DEFAULT_EXCLUSION_FILTER);
}
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}
}
parse调用核心方法processConfigurationClass(ConfigurationClass configClass)解析
class ConfigurationClassParser {
protected void processConfigurationClass(ConfigurationClass configClass, Predicate filter) throws IOException {
//检查当前解析的配置bean是否包含Conditional注解,如果不包含则不需要跳过
// 如果包含了则进行match方法得到匹配结果,如果是符合的并且设置的配置解析策略是解析阶段不需要调过
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
//在这里处理Configuration重复import
//如果同一个配置类被处理两次,两次都属于被import的则合并导入类,返回。如果配置类不是被导入的,则移除旧使用新的配置类
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
// Explicit bean definition found, probably replacing an import.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
// Recursively process the configuration class and its superclass hierarchy.
SourceClass sourceClass = asSourceClass(configClass, filter);
//递归解析
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
}
while (sourceClass != null);
// 添加到ConfigurationClassParser的configurationClasses中
this.configurationClasses.put(configClass, configClass);
}
}
递归解析,调用doProcessConfigurationClass方法,终于到了解析的地方,继续深入
class ConfigurationClassParser {
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)
throws IOException {
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first 处理内部类
processMemberClasses(configClass, sourceClass, filter);
}
// Process any @PropertySource annotations
// 处理@PropertySource注解
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
// 处理@ComponentScan注解
Set 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
Set scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
//遍历扫描到的配置类进行递归解析
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @Import annotations
// 处理@Import注解
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// Process any @ImportResource annotations
// 处理@ImportResource 注解
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
// 遍历配置的locations,加入到configClass 中的ImportedResource
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// Process individual @Bean methods
// 处理@Bean修饰的方法
Set beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
// 处理接口定义的方法
processInterfaces(configClass, sourceClass);
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null;
}
}
解析doProcessConfigurationClass方法,总结一下:
- 1、处理内部类
- 2、处理@PropertySource注解
- 3、处理@ComponentScan注解
- 4、处理@Import注解
- 5、处理@ImportResource注解
- 6、处理@Bean修饰的方法
- 7、处理接口定义的方法
- 8、处理父类
1、处理内部类(递归解析)
class ConfigurationClassParser {
/**
* Register member (nested) classes that happen to be configuration classes themselves.
* 处理内部类
*/
private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,
Predicate filter) throws IOException {
//读取配置类中所有成员类
Collection memberClasses = sourceClass.getMemberClasses();
if (!memberClasses.isEmpty()) {
List 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), filter);
}
finally {
//解析完出栈
this.importStack.pop();
}
}
}
}
}
}
2、处理@PropertySource注解
如果配置类上有@PropertySource注解,则解析加载properties文件,并将属性添加到Spring上下文中。
深入processPropertySource(propertySource)方法
class ConfigurationClassParser {
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");
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);
addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
}
catch (IllegalArgumentException | FileNotFoundException | UnknownHostException ex) {
// Placeholders not resolvable or resource not found when trying to open it
if (ignoreResourceNotFound) {
if (logger.isInfoEnabled()) {
logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
}
}
else {
throw ex;
}
}
}
}
private void addPropertySource(PropertySource> propertySource) {
String name = propertySource.getName();
MutablePropertySources propertySources = ((ConfigurableEnvironment) this.environment).getPropertySources();
//如果存在同名的PropertySource,
// 则使用CompositePropertySource替换原来的PropertySource,
// 而CompositePropertySource中包含了所有的PropertySource
if (this.propertySourceNames.contains(name)) {
// We've already added a version, we need to extend it
PropertySource> existing = propertySources.get(name);
if (existing != null) {
PropertySource> newSource = (propertySource instanceof ResourcePropertySource ?
((ResourcePropertySource) propertySource).withResourceName() : propertySource);
if (existing instanceof CompositePropertySource) {
//将新的PropertySource添加到第一个,使用时在该组中最后一个使用。
((CompositePropertySource) existing).addFirstPropertySource(newSource);
}
else {
if (existing instanceof ResourcePropertySource) {
existing = ((ResourcePropertySource) existing).withResourceName();
}
CompositePropertySource composite = new CompositePropertySource(name);
composite.addPropertySource(newSource);
composite.addPropertySource(existing);
propertySources.replace(name, composite);
}
return;
}
}
/**
* 如果没有同名的PropertySource,当只有一个的时候,直接添加到propertySources中
* 否则将新的PropertySource添加到除systemProperties
* systemEnvironment变量紧接着的第一个(意思就是后添加的后使用,但是如果他们存在同名的属性,后使用的PropertySource会覆盖先使用的)
*/
if (this.propertySourceNames.isEmpty()) {
propertySources.addLast(propertySource);
}
else {
/**
* propertySourceNames中存放的是自定义的PropertySource name,不包含systemProperties systemEnvironment
* 因此每次添加的新PropertySource都是在列表中的第三个(得出此结论的前提框架不在添加其他默认的PropertySource)
*/
String firstProcessed = this.propertySourceNames.get(this.propertySourceNames.size() - 1);
propertySources.addBefore(firstProcessed, propertySource);
}
this.propertySourceNames.add(name);
}
}
3、处理@ComponentScan注解
获取配置类上的@ComponentScan注解,判断是否需要跳过。循环所有的ComponentScan,立即执行扫描。
// Process any @ComponentScan annotations
// 处理@ComponentScan注解
Set 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
Set scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
//遍历扫描到的配置类进行递归解析
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
//检验扫描获得的BeanDefinition中是否有配置类,如果有配置类,这里的配置类包括FullConfigurationClass和LiteConfigurationClass。
//(也就是说只要有@Configuration、@Component、@ComponentScan、@Import、@ImportResource和@Bean中的其中一个注解),则递归调用parse方法,进行解析。
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
继续深入分析
Set scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
class ComponentScanAnnotationParser {
private final Environment environment;
private final ResourceLoader resourceLoader;
private final BeanDefinitionRegistry registry;
public Set parse(AnnotationAttributes componentScan, final String declaringClass) {
//根据@ComponentScan的useDefaultFilters值来构建一个ClassPathBeanDefinitionScanner
//默认为true 如果为true 会注册一些默认的注解过滤器,例如@Component @ManagedBean 和 @Named
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
//类名生成器,默认为BeanNameGenerator接口
Class extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
//为scanner设置类名生成器,默认为AnnotationBeanNameGenerator 如果不填则为类名且首字母小写
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
BeanUtils.instantiateClass(generatorClass));
ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
//scopedProxy默认为DEFAULT
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
scanner.setScopedProxyMode(scopedProxyMode);
}
else {
//scopeResolver默认为AnnotationScopeMetadataResolver
Class extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
}
//设置资源匹配器 默认为**/*.class 即所有class
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
//找到所有的设置的filter 默认为空
for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addIncludeFilter(typeFilter);
}
}
//找到所有排除的filter ,springboot默认有TypeExcludeFilter和AutoConfigurationExcludeFilter
for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addExcludeFilter(typeFilter);
}
}
//是否懒加载 默认为false
boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
scanner.getBeanDefinitionDefaults().setLazyInit(true);
}
Set basePackages = new LinkedHashSet<>();
//找到所有的扫描路径
String[] basePackagesArray = componentScan.getStringArray("basePackages");
//解析每个路径 默认这儿为空
for (String pkg : basePackagesArray) {
//解析这些路径
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
//将解析出来的路径添加到原有的路径中
Collections.addAll(basePackages, tokenized);
}
//如果有basePackageClasses则添加 默认为null
for (Class> clazz : componentScan.getClassArray("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
//如果上述的全部为空 则添加声明类的所在包
//这也就是为何@SpringbootApplication默认只解析其所在的包下面的所有的类,其上级包没法解决
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));
}
}
这个方法很长,但内容很简单,无非就是挨个解析@ComponentScan的值并将其设置到ClassPathBeanDefinitionScanner中,然后调用scanner的解析方法,这儿有两点需要注意
- 1、默认的includeFilter中加入了@Component注解,这个非常重要
- 2、如果注解中没有找到任何可用的basePackage,那么会默认使用传入类的package作为basePackage,而这儿第一次进来的一般为主启动类,所以@springbootApplication之所以默认是解析其类所在的包下所有的类的缘由就在于此。
然后我们接着看doScan方法
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
private BeanNameGenerator beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
protected Set doScan(String... basePackages) {
//做下判空
Assert.notEmpty(basePackages, "At least one base package must be specified");
//创建返回set
Set beanDefinitions = new LinkedHashSet<>();
//迭代每个basePackage
for (String basePackage : basePackages) {
//找到basePackage下所有的配置类
Set candidates = findCandidateComponents(basePackage);
//处理这次找到的所有配置类
for (BeanDefinition candidate : candidates) {
//获取其Scope信息,也就是分析其@Scope注解
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
//设置其scope
candidate.setScope(scopeMetadata.getScopeName());
//这儿会获取名字,如果没有默认为其类名且首字母小写
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
//如果配置类的BeanDefinition继承了AbstractBeanDefinition
if (candidate instanceof AbstractBeanDefinition) {
//则为这个candidate根据刚才初始化时构建的beanDefinitionDefaults来设置BeanDefinition一些属性,
//例如是否懒加载,自动装配模型等
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
//如果配置类 的BeanDefinition实现了AnnotatedBeanDefinition接口
//例如有@Lazy @Primary @DependsOn @Role @Description等注解
if (candidate instanceof AnnotatedBeanDefinition) {
//那么就对其每个注解进行特定的处理 例如Lazy设置懒加载
// 例如Primary设置该类为主要类(例如一个接口有多个实现时,某个实现类加上这个就可以直接使用@Autowire注解不会报错)
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
//检查一下该配置类是否在registray中已存在。为true则代表无冲突,否则会报异常
//例如两个类名一样且都使用@Component注解没有指定姓名就会报错这儿
if (checkCandidate(beanName, candidate)) {
//如果没问题则构造一个BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
//这儿是根据scope信息来判定是否需要需要生成代理 默认不生成
//如果要生成可以为配置类加上@Scope(proxyMode = ScopedProxyMode.DEFAULT) 即可//只要不为ScopedProxyMode.NO(默认属性)即可
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//将该配置类注入到spring的registry中
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
}
这个方法主要就是根据basePackage找到所有的配置类并创建BeanDefinition返回,然后为BeanDefinition设置一些必要的属性,最后根据特定的注解做一些特殊的判断即可。最后这些配置类代表的BeanDefinitionHolder 会被添加到spring的regitry中,在后面实例化的时候将会有很大的作用。
那我们还是接着看下basePackage下的Bean是如何被找到的,我们接着看findCandidateComponents方法。
public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
public Set findCandidateComponents(String basePackage) {
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
return scanCandidateComponents(basePackage);
}
}
private Set scanCandidateComponents(String basePackage) {
Set candidates = new LinkedHashSet<>();
try {
//找到解析的路径匹配规则 resourcePattern默认为**/*.class 即所有的class
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
//根据路径去循环递归查找路径所包含的每一个class文件
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
for (Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
//循环处理每个可读的class文件
if (resource.isReadable()) {
try {
//读取文件的元数据
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
//如果文件在includeFilter中 且没有包含在excludeFilters中 则说明是我们需要加入到容器中的配置类
if (isCandidateComponent(metadataReader)) {
//新建ScannedGenericBeanDefinition (注意其实现了AnnotatedBeanDefinition接口,且集成了AbstractBeanDefinition类)
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
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 (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to read candidate component class: " + resource, ex);
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because not readable: " + resource);
}
}
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
//返回
return candidates;
}
}
这个方法就很简单了,系统解析了路径,并找到路径下所有的class文件,那么spring怎么知道哪些是需要加载配置的呢,这时在上面着重让大家记住的includeFilter就起作用了,由于其加入了@Component注解的支持,我们看这个isCandidateComponent方法。
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
return false;
}
看了这个方法相信大家就了然了,只有includeFilter为true才会返回true,这儿还有点需要注意的是isConditionMatch,这个处理的是@Conditional系列的注解,用来判定是否满足加载配置的条件。如果不满足则不必加载,会返回false。
来看component-scan的几个属性
basePackages:Spring将扫描的基础package名,Spring会扫描该包以及其子孙包下的所有类。
useDefaultFilters:默认为true,此时Spring扫描类时发现如果其被标注为 @Component、@Repository、@Service、@Controller则自动实例化为bean并将其添加到上下文中,如果设置为false,即使将其标注为@Component或者其他,Spring都会忽略。
includeFilters:指定扫描时需要实例化的类型,我们可以从名字看到这是一个Filter,你可以自己定义该Filter,Spring为我们提供了一套方便的实现,我们可以根据标注、类、包等相关信息决定当扫描到该类时是否需要实例化该类,需要注意的是如果你仅仅想扫描如@Controller不仅要加includeFilters,还需要将useDefaultFilters设置为false
excludeFilter:指定扫描到某个类时需要忽略它,实现和上一个Filter一样,区别只是如果Filter匹配,Spring会忽略该类。
这样includeFilters以及excludeFilterF的行为就很清楚了,Spring每扫描一个类,都会经过includeFilters以及excludeFilters,如果某个Filter匹配,就执行相应的操作(实例化或者忽略)。
接着回到doScan方法中,该方法最后会调用registerBeanDefinition(definitionHolder, this.registry)方法,将扫描出来的BeanDefinition注册到到spring的容器中
//将该配置类注入到spring的registry中
registerBeanDefinition(definitionHolder, this.registry);
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
}
public abstract class BeanDefinitionReaderUtils {
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
// 使用beanName做唯一标识注册
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
// 注册所有的别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
}
- 最终将解析出来的BeanDefinition封装到BeanDefinitionHolder中,由BeanDefinitionReaderUtils的registerBeanDefinition方法将BeanDefinition注册到Spring IOC容器中。
- 最终调用DefaultListableBeanFactory类的registerBeanDefinition方法将beanDefinition注册到beanDefinitionMap中。
4、处理@Import注解
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
processImports方法负责对@Import注解进行解析。configClass是配置类,sourceClass又是通过configClass创建的,getImports(sourceClass)从sourceClass获取所有的@Import注解信息
class ConfigurationClassParser {
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection importCandidates, Predicate exclusionFilter,
boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
return;
}
//循环导入直接报错
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
//推入栈
this.importStack.push(configClass);
try {
//循环遍历
for (SourceClass candidate : importCandidates) {
//对import的内容进行分类
// import导入实现ImportSelector接口的类
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class> candidateClass = candidate.loadClass();
// 反射创建这个类的实例对象
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
//是否有实现相关Aware接口,如果有,这调用相关方法
Predicate selectorFilter = selector.getExclusionFilter();
// 延迟加载的ImportSelector
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
if (selector instanceof DeferredImportSelector) {
// 延迟加载的ImportSelector先放到List中,延迟加载
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
// 普通的ImportSelector ,执行其selectImports方法,获取需要导入的类的全限定类名数组
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
// 递归调用
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
}
// 是否为ImportBeanDefinitionRegistrar
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
// 添加到成员变量
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
// 普通 @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
// 解析导入的@Configuration class
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();
}
}
}
}
5、处理@ImportResource注解
@ImportResource注解可以导入xml配置文件。
// Process any @Import annotations
// 处理@Import注解
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// Process any @ImportResource annotations
// 处理@ImportResource 注解
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
// 遍历配置的locations,加入到configClass 中的ImportedResource
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
//把配置项提取出来,跟reader一起放入configClass的map中,
//接下来会在ConfigurationClassPostProcessor类中processConfigBeanDefinitions方法中,解析完,
//this.reader.loadBeanDefinitions(configClasses)这方法会对@import处理(对ImportBeanDefinitionRegistrars的处理)
configClass.addImportedResource(resolvedResource, readerClass);
}
}
6、处理@Bean修饰的方法
// Process individual @Bean methods
// 处理@Bean修饰的方法
Set beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
//添加到configClass的beanMethods集合中,接下来,会在this.reader.loadBeanDefinitions(configClasses)这方法
//得到处理
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
7、处理接口定义的方法
// Process default methods on interfaces
// 处理接口定义的方法
processInterfaces(configClass, sourceClass);
8、处理父类
// Process superclass, if any
// 8.如果有父类则递归读取父类
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;
参考:
https://www.abboke.com/jsh/2019/0628/4154.html
https://www.cnblogs.com/ZhuChangwu/p/11674684.html
https://blog.csdn.net/tuoni123/article/details/79976105
https://www.cnblogs.com/TimeSay/p/10874476.html
https://zhuanlan.zhihu.com/p/83473498
https://www.cnblogs.com/hello-shf/p/10987360.html
https://www.cnblogs.com/duanxz/p/11239291.html
https://www.cnblogs.com/mufeng07/p/12165616.html
https://www.cnblogs.com/mufeng07/p/12172549.html
https://www.cnblogs.com/hetutu-5238/p/12378432.html