再次解释Spring中一个bean的注入过程

目录

一. 前置知识学习

  1. 参考博客
  1. Spring refresh() 方法详解(启动Spring,bean的创建过程) Spring IOC 过程
  2. Spring Bean 源码解析初始化与销毁通,与循环依赖问题
  3. Spring 事件驱动模型开发
  4. 面试题整理. 七 Spring 相关
  5. 面试题整理. 九 SpringBoot/Cloud

Spring中对bean的分类

  1. Spring在服务启动时针对功能,创建顺序的不同等,对bean进行了分类,提出了
  1. BeanDefinition: 存储了bean的定义信息,可以看为bean的描述,在创建bean对象时会先读取到该bean的定义信息转换为BeanDefinition,然后在合适的时机通过这个BeanDefinition创建出对应的bean
  2. BeanDefinitionRegistry: 可以看为BeanDefinition管理器或者仓库管理了BeanDefinition
  3. BeanFactory : bean工厂,用来管理bean的获取,创建,销毁等
  4. BeanFactoryPostProcessor: bean工厂的后置处理器,内部有一个特殊的方法postProcessBeanFactory()
  5. BeanPostProcessors: bean的后置处理器内部有两个特殊的方法,用来监听指定bean进行特殊处理
  6. Aware: 一个能被Spring监听感知的标识接口,当判断是该类型时可以进行一些特殊处理

1. BeanDefinition

  1. 用来存储bean的定义信息,class的描述,在服务启动时将扫描到的class解析为BeanDefinition,后续会通过BeanDefinition创建对应的bean对象
  2. 项目启动时会先扫描获取到指定bean信息后,将解析到的bean的路径保存到BeanDefinition的class属性,bean的模式保存到scope属性属性中,bean属性的初始化值保存到property中…,最终将得到的BeanDefinition存储到beanDefinitionMap中
  3. 后续IOC注入的流程,创建BeanFactory,加载所有BeanDefinition,通过BeanFactory.getBean()–>createBean()–>通过beanName在beanDefinitionMap中获取到对应的BeanDefinition,拿到这个bean的class属性也就是路径,通过反射调用构造器创建…那么BeanDefinition是在哪一步读取进入的呢: 是在invokeDifinitionRegistryPostProcessor()
  4. BeanDefinition是定义Bean的配置元信息的接口内部包含
    在这里插入图片描述
  5. BeanDefinition的继承关系: 继承了AttributeAccessor和BeanMetadataElement两个接口
    在这里插入图片描述
  6. RootBeanDefinition: 是 Spring BeanFactory 运行时统一的 BeanDefinition 视图,代表了一个 merged bean definition,是 Spring BeanFactory 在运行时支持的一个特殊的 bean,也就是Spring 在通过 BeanDefinition 创建 bean 的实例时,通常都会将 BeanDefinition 转化为 RootBeanDefinition 后,再进行 bean 实例的创建, 但是自 Spring 2.5 以来,以编程方式注册 bean 定义的首选方法是 GenericBeanDefinition ,优点是它允许动态定义父依赖项,而不是将角色“硬编码”为 RootBeanDefinition
  7. GenericBeanDefinition: 以编程方式注册 BeanDefinition 的首选类,除了可以指定一些基本的 BeanDefinition 属性外,还可以通过“setParentName()”来灵活地配置 parent bean definition,基本上可以完全替代掉 ChildBeanDefinition
  8. ChildBeanDefinition: 一种可以继承 parent 配置的 BeanDefinition,在创建 bean 时,会通过 AbstractBeanFactory#getMergedLocalBeanDefinition() 来将 child 和 parent bean definition 进行合并(Spring 2.5 之后,推荐通过 GenericBeanDefinition#setParentName() 的方式来替代 ChildBeanDefinition)
  9. merged bean definition: 是 Spring 对 BeanDefinition 进行的一种合并操作,会将 child 的属性与 parent 的属性进行合并,当有相同属性时,以 child 的为准,什么时候会对 BeanDefinition 进行 merge 操作: AbstractBeanFactory#getMergedLocalBeanDefinition() 来进行 merge 操作

2. BeanFactoryPostProcess

  1. BeanFactoryPostProcessor 是一个接口,该接口中有一个 postProcessBeanFactory() 抽象方法,与 BeanPostProcessor 不同的的是:
  1. BeanPostProcessor 是 bean 的后置处理器,监控 bean 的创建,在Bean的初始化前后,拦截执行 BeanPostProcessor 中的方法
  2. BeanFactoryPostProcess 可以看为是更上一层的后置处理器,(可以理解为 BeanFactory 的后置处理器)当所有 bean 加载完成放入BeanFactory 后,但是还未创建时执行该接口中的方法

3. BeanDefinitionRegistryPostProcessor

  1. BeanFactoryPostProcess 如果细分的话,其下层还有继承于该接口的 BeanDefinitionRegistryPostProcessor,多了一个postProcessBeanDefinitionRegistry()方法,进而得知实现BeanDefinitionRegistryPostProcessor接口的类需要重新两个抽象方法
  1. BeanFactoryPostProcess 中的 postProcessBeanFactory()
  2. BeanDefinitionRegistryPostProcessor 中的 postProcessBeanDefinitionRegistry()

4. BeanPostProcessors 后置处理器

  1. 先了解一下BeanPostProcessor接口中的两个方法
  1. postProcessBeforeInitialization(Object o, String s) 初始化 bean 之前需要执行的方法,
  2. postProcessAfterInitialization(Object o, String s) 初始化bean之后需要执行的方法,
  3. 后续在创建bean 向容器中注入时首获取容器中所有存在的BeanPostProcessors对象,在初始化当前bean的前后执行这两个方法
  4. 这两个方法中都有两个参数 Object o, String s, o代表执行初始化的bean, s 代表这个 bean 在容器中的 id
  1. 在向Spring中注入bean时会优先注入该类型的bean,后续Spring注入其它类型的bean时在初始化前后执行postProcessBeforeInitialization()与postProcessAfterInitialization()两个方法
  2. 还有一个后置处理器接口 InstantiationAwareBeanPostProcessor 该接口继承 BeanPostProcessor 接口, 比 BeanPostProcessor 接口中多了一个 postProcessBeforeInstantiation() 方法, 该方法是在,创建 bean 前执行的
  3. 那么BeanPostProcessors中的两个方法是在什么时候调用的:具体要了解Spring IOC的过程, 在启动Spring容器时会先创建BeanFactory, 创建BeanFactoryPostProcessor类型的bean对象,然后创建BeanPostProssor注入到容器中,最后再创建其它单实例bean,创建bean对象时会调用getBean(),getSingleton()方法,通过beanName在容器中获取,如果不存在,调用一个doCreateBean()方法创建,对象创建后执行populateBean()装配bean的依赖,然后执行initializeBean(), 查看initializeBean()内部,重点关注内部调用的四个方法
  1. invokeAwareMethods() ,通过该方法,判断要初始化的bean 是否是某个Aware类型,通过执行接口中的setXX()方法(Aware,通常用来获取 Spring 提供的组件,通过重写的抽象方法赋值给当前初始化的 bean)
  2. applyBeanPostProcessorsBeforeInitialization() 通过该方法获取容器中的BeanPostProcessor,执行初始化bean前需要执行的方法postProcessBeforeInitialization()
  3. invokeInitMethods() 方法,通过该方法执行初始化方法(例如调用InitializingBean的afterPropertiesSet,调用自定义的init-method 等)
  4. applyBeanPostProcessorsAfterInitialization() 通过该方法获取容器中的BeanPostProcessor,执行初始化bean后需要执行的方法postProcessAfterInitialization()

5. Aware 接口

  1. Aware接口没有任何定义,仅仅是一个声明,起到一个标识的作用, 实现了Aware接口的类就会被Spring容器所感知。而具体需要感知什么内容需要具体的子接口去定义, 每个Aware接口的子接口,内部都需要有一个set方法,将本身设置进去,这样实现了该接口的类就可以获取到该对象了
  2. 以BeanFactoryAware接口为例: BeanFactoryAware接口中有setBeanFactroy(BeanFactroy beanFactory)方法,子类实现了之后,可以得到beanFactory对象了。同理实现了XXXAware接口,就可以得到XXX这个对象
  3. Spring中提供的实现了Aware接口的子类
  1. BeanFactoryAware接口(获取BeanFactory对象)
  2. ApplicatioContextAware接口(获取ApplicationContext对象)
  3. BeanNameAware接口(获取当前bean的beanName)
  4. ApplicationEventPublisherAware接口(获取容器中事件发布器,可以用于发布事件)
  5. ResourceLoaderAware接口(获取资源加载器,用于获取外部资源文件)

6. BeanFactory 与 ApplicationContext有什么区别

  1. ApplicationContext 实现了BeanFactory 接口,并重写了getBean()方法, 在重写方法中实际是先getBeanFactory()获取到BeanFactory,然后通过BeanFactory再去getBean()的,ApplicationContext 不会去创建bean,而是获取BeanFactory通过BeanFactory去创建,ApplicationContext 功能更多例如加载环境变量,实现事件监听,注册其它扩展点等等

7. BeanFactory 与 FactoryBean 有什么区别

  1. BeanFactory 是一个Bean工厂用来管理和生产bean的

Spring启动时执行obtainFreshBeanFactory()首先会创建BeanFactory, 默认情况下会创建一个 DefaultListableBeanFactory类型的 bean工厂赋值给 beanFactory 属性,然后再创建其它bean,管理了bean的生产,初始化,销毁生命周期

  1. 而FactoryBean 是一个接口,必须被一个bean来实现,被BeanFactory管理,但不是一个普通的bean,可以看为是一个工厂方法模式,内部有一个getObject()方法,用来获取FactoryBean生产的对象,也就是说继承FactoryBean接口的bean,当获取该bean时,并不是通过构造器返回的,底层实际会执行重写的getObject()方法,通过该方法返回一个实例,继承FactoryBean的bean是懒加载,如果想要返回实际的可以通过"&"符去获取原实例,
    在这里插入图片描述

8. 重点:预习Spring中创建不同类型bean的先后顺序

  1. Spring启动时会调用run方法,在run方法中首先会创建ApplicationContext上下文,执行refresh()方法创建bean,先简述一下内部流程
  1. 首先Spring启动时会扫描获取的bean的定义信息,比如class文件,xml文件等,将获取到的bean信息封装为BeanDefinition
  2. 创建BeanDefinitionRegistry也就是用来管理BeanDefinition的仓库,创建BeanFactory用来管理bean的工厂
  3. 接着开始实例化bean
  4. 先获取BeanFactoryPostProcessor工厂后置处理器类型的bean调用它的postProcessBeanFactory()方法,或者获取实际类型是BeanFactoryPostProcessor的BeanDefinition,进行初始化创建,然后执行postProcessBeanFactory()方法
  5. 接着获取BeanPostProcessors后置处理器类型的BeanDefinition优先将该类型的bean初始化创建
  6. 初始化事件派发器,多播器ApplicationEventMulticaster
  7. 注册监听器ApplicationListener
  8. 完成ben的创建初始化工作,完成 IOC 容器的创建,发布容器刷新完成事件
  9. 最后再创建其它单利bean,在创建初始化前后会被BeanPostProcessors监控到,对指定类型的bean进行一些特殊处理
  1. 先后顺序为: run()方法启动—>ApplicationContext创建上下文—>创建BeanDefinition 注解解析器AnnotatedBeanDefinitionReader—>BeanDefinition扫描器ClassPathBeanDefinitionScanner---->创建BeanDefinitionRegistry—>BeanFactory—>BeanDefinition xml解析器 XmlBeanDefinitionReade—>基于BeanDefinition注解解析器,扫描器,xml解析器扫描bean资源将bean转换为BeanDefinition—>创建BeanFactoryPostProcessor—>BeanPostProcessors—>创建ApplicationEventMulticaster事件派发器多播器—>注册监听器ApplicationListener—>其它单实例bean—>完成ben的创建初始化工作,完成 IOC 容器的创建,发布容器刷新完成事件

二. 由SpringBoot启动run()源码引出ApplicationContext上线文的创建与基于注解的BeanDefinition读取器AnnotatedBeanDefinitionReader和基于ClassPath路径下的BeanDefinition扫描器ClassPathBeanDefinitionScanner

  1. 首先要了解几个问题,Spring支持
  1. 基于XML配置
  2. Spring2.5+提出, 基于注解例如配置中使用< component-scan> 开启包扫描,基于包扫描,与注解进行注入
  3. 在Spring3.0后又提出基于javaConfig配置方式,可以使用:@Configuration, @Bean,@PropertySource, @Value, @ComponentScan
  1. 通过问题引出底层源码
  1. 基于什么实现XML配置: 针对解析xml提供了BeanDefinition xml解析器 XmlBeanDefinitionReade
  2. 包扫描装配是怎么实现的: 针对包扫描提供了BeanDefinition 扫描器 ClassPathBeanDefinitionScanner
  3. 注解装配是怎么实现的: 针对javaConfig注解方式提供了基于注解的BeanDefinition解析器AnnotatedBeanDefinitionReader
  1. 接下来就要找到AnnotatedBeanDefinitionReader, ClassPathBeanDefinitionScanner,XmlBeanDefinitionReade是什么时候创建的
  2. SpringBoot启动代码示例,启动SpringBoot项目需要调用SpringApplication的run()方法
@SpringBootApplication
public class TestActuatorApplication {
    public static void main(String[] args) {
        SpringApplication.run(TestActuatorApplication.class, args);
    }
}
  1. 查看run方法底层,会调用多个重载的run方法
	public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
        return run(new Class[]{primarySource}, args);
    }
	
	public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        return (new SpringApplication(primarySources)).run(args);
    }

	public ConfigurableApplicationContext run(String… args) { 
		// 创建一个计时器,用于记录启动时间 
		StopWatch stopWatch = new StopWatch(); // 开始计时 stopWatch.start(); 
		// 声明一个可配置的应用上下文对象,用于返回 
		ConfigurableApplicationContext context = null; 
		// 声明一个异常报告器的集合,用于处理启动过程中的异常 
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); 
		// 配置 headless 属性,用于判断是否是无头模式(没有显示器、键盘或鼠标的系统) 
		this.configureHeadlessProperty(); 
		// 获取 SpringApplicationRunListener 的实例,用于监听启动过程中的事件 
		SpringApplicationRunListeners listeners = this.getRunListeners(args); 
		// 通知所有的监听器,应用正在启动 
		listeners.starting();

		Collection exceptionReporters;
		try {
    		// 创建一个应用参数对象,用于封装命令行参数
    		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
    		// 准备环境对象,用于配置应用运行时的环境变量
    		ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
    		// 配置是否忽略 BeanInfo 的属性信息,以提高性能
    		this.configureIgnoreBeanInfo(environment);
    		// 打印 banner 图案,如果有的话
    		Banner printedBanner = this.printBanner(environment);
    		// TODO 重点:创建应用上下文对象,根据不同的 web 类型选择不同的实现类
    		context = this.createApplicationContext();
    		// 获取 SpringBootExceptionReporter 的实例,用于处理启动过程中的异常
    		exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
    	// 准备应用上下文对象,设置环境、注册监听器、加载源等操作
    	this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
    	// 刷新应用上下文对象,加载 bean 定义并实例化 bean
    	this.refreshContext(context);
    	// 在刷新后执行一些操作,例如注册关闭钩子等
    	this.afterRefresh(context, applicationArguments);
    	// 停止计时器
    	stopWatch.stop();
    	// 如果启用了日志打印,打印启动信息和耗时
    	if (this.logStartupInfo) {
        	(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
	    }

    	// 通知所有的监听器,应用已经启动完成
    	listeners.started(context);
    	// 调用 ApplicationRunner 和 CommandLineRunner 的实例,执行自定义逻辑
    	this.callRunners(context, applicationArguments);
	} catch (Throwable var10) {
    	// 如果出现异常,处理启动失败的情况,销毁上下文,通知监听器,并抛出异常
    	this.handleRunFailure(context, var10, exceptionReporters, listeners);
    	throw new IllegalStateException(var10);
	}

	try {
    	// 通知所有的监听器,应用正在运行中
    	listeners.running(context);
    	// 返回应用上下文对象
    	return context;
	} catch (Throwable var9) {
    	// 如果出现异常,处理运行失败的情况,并抛出异常
    	this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
    	throw new IllegalStateException(var9);
	}
}
  1. 在最底层调用的run()方法内部,重点关注调用了一个createApplicationContext()方法,根据不同的 web 类型设置不同的上下文的地址,使用反射创建不同的ApplicationContext上下文对象
  1. NONE 表示普通的 JAVA 程序,不涉及 web 容器,默认情况下创建AnnotationConfigApplicationContext
  2. SERVLET 表示使用 servlet 作为 web 容器,一般使用的就是这种类型,该类型时创建AnnotationConfigServletWebServerApplicationContext上下文
  3. REACTIVE 是在 Spring 5 之后新增的一种应用类型,也是一种 web 框架,但并不是基于 servlet,而是基于 reactive,该类型时创建AnnotationConfigReactiveWebServerApplicationContext上下文
protected ConfigurableApplicationContext createApplicationContext() {
        Class<?> contextClass = this.applicationContextClass;
        if (contextClass == null) {
            try {
                switch(this.webApplicationType) {
                case SERVLET:
                    contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
                    break;
                case REACTIVE:
                    contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
                    break;
                default:
                    contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
                }
            } catch (ClassNotFoundException var3) {
                throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
            }
        }

        return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
    }
  1. 以上几种ApplicationContext上下文的基本介绍:
  1. AnnotationConfigServletWebServerApplicationContext:这个上下文是用于基于Servlet的web应用程序的,它继承自WebApplicationContext接口,可以支持web相关的功能,如ServletContext、ServletConfig等。它也可以使用注解来配置bean定义,而不需要XML文件
  2. AnnotationConfigReactiveWebServerApplicationContext:这个上下文是用于基于Reactive的web应用程序的,它继承自ReactiveWebApplicationContext接口,可以支持Reactive相关的功能,如WebFlux、Netty等。它也可以使用注解来配置bean定义,而不需要XML文件
  3. AnnotationConfigApplicationContext:这个上下文是用于非web应用程序的,它继承自GenericApplicationContext接口,可以支持一般的功能,如事件发布、资源加载等。它也可以使用注解来配置bean定义,而不需要XML文件
  1. 查看以上几种ApplicationContext上下文对象的构造器,发现以上几种上下文对象的构造器中都初始化了基于注解的BeanDefinition读取器AnnotatedBeanDefinitionReader,基于ClassPath路径下的BeanDefinition扫描器ClassPathBeanDefinitionScanner
	public AnnotationConfigApplicationContext() {
		//基于注解的BeanDefinition读取器
        this.reader = new AnnotatedBeanDefinitionReader(this);
        //基于ClassPath路径下的BeanDefinition扫描器
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

1. AnnotatedBeanDefinitionReader引出一系列BeanFactoryPostProcessor,BeanPostProcessor的注册

  1. 问题AnnotatedBeanDefinitionReader 是怎么获取被注解修饰的bean进行解析创建的,这里就要了解BeanPostProcessor
  2. 继续查看创建BeanDefinition注解解析器AnnotatedBeanDefinitionReader的构造函数
	public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
        this(registry, getOrCreateEnvironment(registry));
    }

	public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) { 
		// 创建一个注解bean名称生成器,用于根据注解生成bean的名称 
		this.beanNameGenerator = new AnnotationBeanNameGenerator(); 
		// 创建一个注解作用域元数据解析器,用于根据注解解析bean的作用域 
		this.scopeMetadataResolver = new AnnotationScopeMetadataResolver(); 
		// 断言注册表和环境对象不能为空,否则抛出异常 
		Assert.notNull(registry,BeanDefinitionRegistry must not be null); 
		Assert.notNull(environment,Environment must not be null); 
		// 保存注册表和条件评估器对象,用于后续操作,ConditionEvaluator用于解析 Condition 相关注解
		//在注册 BeanDefinition 之前,会根据其 @Conditional 注解的条件进行过滤
		this.registry = registry; this.conditionEvaluator = new ConditionEvaluator(registry, environment, (ResourceLoader)null); 
		//注册一些注解配置处理器到注册表中,
		//用于处理@Configuration、@ComponentScan、@Import、@ImportResource等注解 
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); 
	}
  1. 在BeanDefinition注解解析器AnnotatedBeanDefinitionReader的构造函数中,首先重点关注调用的AnnotationConfigUtils的registerAnnotationConfigProcessors()方法,通过该方法会优先创建一系列BeanPostProcessor的BeanDefinition,保存到beanDefs一个set集合中,例如:
  1. ConfigurationClassPostProcessor: 非常重要下方有解释
  2. AutowiredAnnotationBeanPostProcessor: 用来支持 @Autowired @Value 等注解的解析
  3. CommonAnnotationBeanPostProcessor: 引入 了JSR-250 相关依赖,可以处理@PostConstruct和@PreDestroy还有@Resource等
  4. PersistenceAnnotationBeanPostProcessor: 引入了 JPA 相关依赖且不存在对应 BeanDefinition 则注册,支持 JPA 相关后处理
  5. EventListenerMethodProcessor:负责对 @EventListener 注解标注的方法进行处理
  6. DefaultEventListenerFactory: 主要由 EventListenerMethodProcessor 使用,用来基于 @EventListener 注解标注的方法获取对应 ApplicationListener
	public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
    public static final String CONFIGURATION_BEAN_NAME_GENERATOR = "org.springframework.context.annotation.internalConfigurationBeanNameGenerator";
    public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
    /** @deprecated */
    @Deprecated
    public static final String REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalRequiredAnnotationProcessor";
    public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalCommonAnnotationProcessor";
    public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalPersistenceAnnotationProcessor";
    private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME = "org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor";
    public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME = "org.springframework.context.event.internalEventListenerProcessor";
    public static final String EVENT_LISTENER_FACTORY_BEAN_NAME = "org.springframework.context.event.internalEventListenerFactory";
    private static final boolean jsr250Present;
    private static final boolean jpaPresent;


	public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
        registerAnnotationConfigProcessors(registry, (Object)null);
    }

    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {

        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
        if (beanFactory != null) {
            if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                //注册了实现Order接口的排序器,后续会通过它实现解析@Order和@Priority
                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
            }
            //设置@AutoWired的候选的解析器
            if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            	//ContextAnnotationAutowireCandidateResolver提供处理延迟加载的功能
                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
            }
        }
		
        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

        //注册解析我们配置类的后置处理器ConfigurationClassPostProcessor
        //org.springframework.context.annotation.internalConfigurationAnnotationProcessor
        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

         //注册处理@Autowired 注解的处理器AutowiredAnnotationBeanPostProcessor
         //org.springframework.context.annotation.internalAutowiredAnnotationProcessor
        if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

         //注册处理@Required属性的注解处理器RequiredAnnotationBeanPostProcessor
         // org.springframework.context.annotation.internalRequiredAnnotationProcessor
        if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

         //注册处理JSR规范的注解处理器CommonAnnotationBeanPostProcessor
         //org.springframework.context.annotation.internalCommonAnnotationProcessor
        if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

		//处理jpa注解的处理器org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor
        if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition();
            try {
                def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                        AnnotationConfigUtils.class.getClassLoader()));
            }
            catch (ClassNotFoundException ex) {
                throw new IllegalStateException(
                        "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
            }
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

		//处理监听方法的注解解析器EventListenerMethodProcessor
        if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
        }

        //注册事件监听器工厂
        if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
        }

        return beanDefs;
    }
  1. 其中ConfigurationClassPostProcessor间接继承了BeanFactoryPostProcessor后置处理器非常重要,会处理不管是手动注册还是扫描机制所有BeanDefinition中符合注解条件的BeanDefinition,过滤出带有相关注解的BeanDefinition包括(@Configuration、@Component、@ComponentScan、@Import、@ImportResource或者@Bean)进行进一步处理
  2. ConfigurationClassPostProcessor到底怎么解析@Bean, @Import, @ComponentScan, @Component…修饰的bean到beanDefinitionMap的,ConfigurationClassPostProcessor是一个后置处理器,在processConfigBeanDefinitions()方法中遍历容器的beanDefinition集合,通过ConfigurationClassUtils工具类找到配置类beanDefinition,将其放入configCandidates集合中,创建ConfigurationClassParser对象,调用对象的parse方法最终会调用doProcessConfigurationClass()方法,扫描对应的注解,进行解析参考博客1参考博客2
  3. 那ConfigurationClassParser怎么扫描的,以 @ComponentScan 为例Spring提供了ClassPathBeanDefinitionSacnner通过该类下的doScan()方法扫描,根据包路径找到所有的.class文件,判断类是不是标准的@Component注解,判断是不是接口,是不是抽象类…
  4. 前面说过Spring将bean分成了不同类型,根据这个类型使其在创建时保证一定的先后顺序,上方先一步将BeanPostProcessor转换为BeanDefinition,根据BeanDefinition注册时间的不同,bean的创建顺序也不同,自此这些带功能的bean会先一步创建注入到容器中,在后续创建其它bean时,就可以通过这些bean感知到,进行特殊处理

2. ClassPathBeanDefinitionScanner扫描bean

  1. 在创建ApplicationContext上下文时查看构造器,内部会创建一个ClassPathBeanDefinitionScanner对象,在Spring 2.5提供的"<context:component-scan base-package=“com.x.y”></context:component-scan>"包扫描就是通过它实现的,一个BefanDefinition扫描器,检测classpath上的bean,判断bean上是否存在指定的@Component(包含@Repository,@Service或@Controller)注解也会扫描JSR-250 的 @ManagedBean 和 JSR-330 的 @Named ,注册响应的BefanDefinition
  2. ConfigurationClassParser怎么扫描的,重点依赖与该类中的scan(), doScan()方法,在Spring启动时有多个位置调用这个方法(注意此时支持创建出来,调用是在下面几个方法中执行的)
  1. Spring启动refresh()内部postProcessBeanFactory()中会调用
  2. refresh()启动refresh()内部invokeBeanFactoryPostProcessors()中会调用
  3. 使用@ComponentScan注解时,这个注解使用几次doScan()就会调用几次
  1. 调用doScan()扫描加载依赖组件的初始化以及将BeanDefinition注册到registry,内部重点:
  1. 调用findCandidateComponents()方法扫描bean,创建BeanDefinition(调用了大量的父类中的方法)
  2. 调用registerBeanDefinition()–>最终会调用到DefaultListableBeanFactory下的registerBeanDefinition()方法注册BeanDefinition,也就是将创建好的BeanDefinition保存到DefaultListableBeanFactory的beanDefinitionMap中
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {

    //bean定义的注册器接口,用于注册BeanDefinition
    private final BeanDefinitionRegistry registry;

    private BeanDefinitionDefaults beanDefinitionDefaults = new BeanDefinitionDefaults();

    @Nullable
    private String[] autowireCandidatePatterns;

    // bean的名称生成器
    private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();

    private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();

    private boolean includeAnnotationConfig = true;

    //构造函数,创建ClassPathBeanDefinitionScanner扫描器,同时根据参数设置filter以及resourceLoader
    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
            Environment environment, @Nullable ResourceLoader resourceLoader) {
        this.registry = registry;
        if (useDefaultFilters) {
           //设置Filter
            registerDefaultFilters();
        }
        //设置environment
        setEnvironment(environment);
        //设置resourceLoader
        setResourceLoader(resourceLoader);
    }
	//扫描给定的包路径,生成BeanDefinition并注册到注册器
    public int scan(String... basePackages) {
        //获取注册器中已注册的bean数量
        int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
        //通过doScan给定包路径并生成BeanDefinition注册到registry中
        doScan(basePackages);
        if (this.includeAnnotationConfig) {
        	//如果includeAnnotationConfig属性为true,就注册一些注解配置处理器到注册表中,
        	//用于处理@Configuration、@ComponentScan、@Import、@ImportResource等注解
            AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
        }
        //返回扫描后与扫描前的bean定义数量之差,即新增的数量
        return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
    }

    //扫描给定的包路径,生成BeanDefinition并注册到注册器
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {

        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
        //遍历给定扫描的包
        for (String basePackage : basePackages) {
           // 调用findCandidateComponents扫描包组装BeanDefinition集合
           //findCandidateComponents方法为父类方法
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
            //遍历BeanDefinition,根据条件将BeanDefinition注册到注册中心
            for (BeanDefinition candidate : candidates) {
            	//调用scopeMetadataResolver解析Bean定义的作用域元数据
                ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
                //设置Bean定义的作用域
                candidate.setScope(scopeMetadata.getScopeName());
                //调用beanNameGenerator生成Bean定义的名称
                String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                //如果Bean定义是AbstractBeanDefinition的子类,那么进行后处理
                if (candidate instanceof AbstractBeanDefinition) {
                    postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
                }
                //如果Bean定义是AnnotatedBeanDefinition的子类,那么处理一些通用的注解
                if (candidate instanceof AnnotatedBeanDefinition) {
                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
                }
                //检查是否有同名的Bean定义已经存在,如果没有,那么继续注册
                if (checkCandidate(beanName, candidate)) {
                	//创建一个Bean定义持有者对象,包含了Bean定义和名称
                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                    //根据作用域元数据,应用代理模式,可能会修改持有者对象
                    definitionHolder =AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                    //将持有者对象添加到集合中
                    beanDefinitions.add(definitionHolder);
                    //调用registerBeanDefinition方法,将持有者对象注册到BeanFactory中
                    registerBeanDefinition(definitionHolder, this.registry);
                }
            }
        }
        return beanDefinitions;
    }
}

findCandidateComponents()将扫描到的class转换为转换为BeanDefinition

  1. doScan()方法中会调用了findCandidateComponents()这个方法是ClassPathBeanDefinitionScanner父类ClassPathScanningCandidateComponentProvider的,查看父类源码, 重点关注:
  1. findCandidateComponents(): 该方法内会继续调用scanCandidateComponents()根据basePackage地址,扫描对应的class文件,
  2. scanCandidateComponents()方法内遍历根据basePackage扫描到的资源,通过getMetadataReader()读取到 metadataReader 也就是当前class的元数据(包括类的地址,类上的注解…等信息),然后创建ScannedGenericBeanDefinition对象,这个就是创建对应的BeanDefinition,最终将BeanDefinition保存到candidates一个Set集合中
public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {

    //默认的资源匹配后缀
    static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
    //资源匹配后缀信息
    private String resourcePattern = DEFAULT_RESOURCE_PATTERN;
    // bean定义包含过滤器,用户过滤查找到的类
    private final List<TypeFilter> includeFilters = new LinkedList<>();
    // bean定义剔除过滤器,用户过滤查找到的类
    private final List<TypeFilter> excludeFilters = new LinkedList<>();
    
    @Nullable
    private Environment environment;

    @Nullable
    private ConditionEvaluator conditionEvaluator;

    //资源路径匹配转换资源的转换器,通过资源匹配字符串在classpath查找匹配到class并将其转换为resource 
    @Nullable
    private ResourcePatternResolver resourcePatternResolver;

    //元数据读取器创建工厂,用于创建元数据的读取器
    @Nullable
    private MetadataReaderFactory metadataReaderFactory;

    //
    @Nullable
    private CandidateComponentsIndex componentsIndex;

    //添加包含过滤器
    public void addIncludeFilter(TypeFilter includeFilter) {
        this.includeFilters.add(includeFilter);
    }

    //添加剔除过滤器
    public void addExcludeFilter(TypeFilter excludeFilter) {
        this.excludeFilters.add(0, excludeFilter);
    }

    //重置过滤器
    public void resetFilters(boolean useDefaultFilters) {
        this.includeFilters.clear();
        this.excludeFilters.clear();
        if (useDefaultFilters) {
            registerDefaultFilters();
        }
    }

    //注册默认的过滤器
    @SuppressWarnings("unchecked")
    protected void registerDefaultFilters() {
        //添加对Component注解匹配的过滤器
        this.includeFilters.add(new AnnotationTypeFilter(Component.class));
        ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
        try {
        	// 添加对javax.annotation.ManagedBean注解匹配的过滤器
            this.includeFilters.add(new AnnotationTypeFilter(
                    ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
        }
        catch (ClassNotFoundException ex) {
            // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
        }
        try {
           // 添加对javax.inject.Named注解匹配的过滤器
            this.includeFilters.add(new AnnotationTypeFilter(
                    ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
        }
        catch (ClassNotFoundException ex) {
            // JSR-330 API not available - simply skip.
        }
    }
	
	//获取资源路径匹配转换资源的转换器,默认为PathMatchingResourcePatternResolver
    private ResourcePatternResolver getResourcePatternResolver() {
        if (this.resourcePatternResolver == null) {
            this.resourcePatternResolver = new PathMatchingResourcePatternResolver();
        }
        return this.resourcePatternResolver;
    }

    //获取元数据读取器创建工厂,默认为CachingMetadataReaderFactory
    public final MetadataReaderFactory getMetadataReaderFactory() {
        if (this.metadataReaderFactory == null) {
            this.metadataReaderFactory = new CachingMetadataReaderFactory();
        }
        return this.metadataReaderFactory;
    }

    //扫描bean,转换为BeanDefinition
    public Set<BeanDefinition> findCandidateComponents(String basePackage) {
		//是否有META-INF/spring.components文件,有的话去读取其中的文件进行bean注册
		if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
			return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
		}
		else {
			//得到带有beanClass属性的beanDefination
			return scanCandidateComponents(basePackage);
		}
	}

    //扫描包将扫描到的class生成BeanDefinition集合
    private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
        Set<BeanDefinition> candidates = new LinkedHashSet<>();
        try {
            //根据包名组装包扫描路径
            String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                    resolveBasePackage(basePackage) + '/' + this.resourcePattern;
                    
            // 通过资源路径匹配转换资源的转换器 生成资源(class类)数组
            Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);

            //遍历资源(class)
            for (Resource resource : resources) {
            
                if (resource.isReadable()) {
                    try {
                        //通过元数据读取器工厂,根据资源生成元数据读取器。
                        // 此处通过asm将class文件读取成元数据模型
                        MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                        //判断元数据是否需要组装成BeanDefinition
                        // 此处判断当前class是否需要注册到spring的IOC容器中,通过IOC容器管理。
                    	//spring默认对Component注解的类进行动态注册到IOC容器
                    	// 通过includeFilters与excludeFilters来判定匹配。
                        if (isCandidateComponent(metadataReader)) {
                           //创建BeanDefinition
                          ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                            sbd.setResource(resource);
                            sbd.setSource(resource);
                            if (isCandidateComponent(sbd)) {
                               //添加到集合中
                                candidates.add(sbd);
                            }
                        }
                    }
                    catch (Throwable ex) {
                    }
                }
            }
        }
        catch (IOException ex) {
        }
        return candidates;
    }

    //通过过滤器判断给定的元数据是否需要组装生成BeanDefinition,spring默认对classpath中的
    // Component,javax.inject.Named,javax.annotation.ManagedBean注解注解的类组装生成BeanDefinition
    protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
        //当元数据通过剔除过滤器时返回false
        for (TypeFilter tf : this.excludeFilters) {
            if (tf.match(metadataReader, getMetadataReaderFactory())) {
                return false;
            }
        }
        //当元数据通过包含过滤器时返回true
        for (TypeFilter tf : this.includeFilters) {
            if (tf.match(metadataReader, getMetadataReaderFactory())) {
                return isConditionMatch(metadataReader);
            }
        }
        return false;
    }
}

registerBeanDefinition() 注册 BeanDefinition 到 BeanFactory 中

  1. 在doScan()中先调用了findCandidateComponents()方法,根据basePackages地址扫描class文件,将class转换成了BeanDefinition, 代码继续向下执行会调用registerBeanDefinition(),最终实现BeanDefinition的注册,也就是将BeanDefinition保存到DefaultListableBeanFactory的beanDefinitionMap中,查看源码
  2. doScan()中调用当前类中的registerBeanDefinition()方法–>调用BeanDefinitionReaderUtils下的registerBeanDefinition()静态方法, 在该方法中会获取到工厂默认情况下是DefaultListableBeanFactory然后执行工厂的registerBeanDefinition()方法实现注册
	protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
    }

	//BeanDefinitionReaderUtils下的registerBeanDefinition()方法,不是一个版本
	public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
        String beanName = definitionHolder.getBeanName();
        //默认调用DefaultListableBeanFactory 工厂上的registerBeanDefinition()方法实现注册
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            String[] var4 = aliases;
            int var5 = aliases.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                String alias = var4[var6];
                registry.registerAlias(beanName, alias);
            }
        }

    }
  1. 查看DefaultListableBeanFactory下的registerBeanDefinition()方法
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");
        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                ((AbstractBeanDefinition)beanDefinition).validate();
            } catch (BeanDefinitionValidationException var9) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var9);
            }
        }

        BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
        if (existingDefinition != null) {
            if (!this.isAllowBeanDefinitionOverriding()) {
                throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
            }

            if (existingDefinition.getRole() < beanDefinition.getRole()) {
                if (this.logger.isInfoEnabled()) {
                    this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
                }
            } else if (!beanDefinition.equals(existingDefinition)) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
                }
            } else if (this.logger.isTraceEnabled()) {
                this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
            }

            this.beanDefinitionMap.put(beanName, beanDefinition);
        } else {
            if (this.hasBeanCreationStarted()) {
                synchronized(this.beanDefinitionMap) {
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    if (this.manualSingletonNames.contains(beanName)) {
                        Set<String> updatedSingletons = new LinkedHashSet(this.manualSingletonNames);
                        updatedSingletons.remove(beanName);
                        this.manualSingletonNames = updatedSingletons;
                    }
                }
            } else {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                this.manualSingletonNames.remove(beanName);
            }

            this.frozenBeanDefinitionNames = null;
        }

        if (existingDefinition != null || this.containsSingleton(beanName)) {
            this.resetBeanDefinition(beanName);
        }

    }

三. refresh()方法执行到BeanFactory的创建—>BeanFactoryPostProcessor—>BeanPostProcessor—>其它单利bean的创建

  1. 通过上面启动项目的run()方法源码我们了解到在启动服务创建ApplicationContext时
  1. 初始化创建了用于解析注解的BeanDefinition解析器AnnotatedBeanDefinitionReader,并且通创建这个解析器是构造器内部调用了AnnotationConfigUtils的registerAnnotationConfigProcessors()注册了一系列的BeanPostProcessor
  2. 初始化创建了BeanDefinition 扫描器 ClassPathBeanDefinitionScanne,后续会在多个位置执行该类中的doScan()方法,根据basePackage路径扫描指定的class,调用findCandidateComponents()将扫描到的class资源封装为ScannedGenericBeanDefinition也就是转换为BeanDefinition, 然后调用registerBeanDefinition() 注册 BeanDefinition 到 BeanFactory 中也就是将BeanDefinition保存到DefaultListableBeanFactory的beanDefinitionMap中
  1. 问题:
  1. BeanDefinition 最终要注册到BeanFactory中,BeanFactory是怎么创建的
  2. AnnotatedBeanDefinitionReader是针对注解的BeanDefinition解析器,ClassPathBeanDefinitionScanne是针对包扫描的BeanDefinition扫描器,那xml配置的bean是怎么处理的
  3. 在创建AnnotatedBeanDefinitionReader时创建一系列的BeanFactoryPostProcessor,BeanPostProcessor,这些后置处理器是如何执行的
  4. 在项目启动过程中会多次执行 ClassPathBeanDefinitionScanne扫描器中的doScan()方法,扫描指定的class进行注册,是在哪发起执行的
  1. 接下来跟着源码解答一下上面的问题,下方只针对上面的问题,其它的就先不做解释了

1. refresh()创建bean工厂,加载并实例化bean方法概述

  1. 先看一下项目启动时如何执行到refresh()这个方法的,在run方法中先创建ApplicationContext,创建完毕后会调用refreshContext(context),内部会调用refresh方法
	private void refreshContext(ConfigurableApplicationContext context) {
		//刷新应用上下文对象,加载 bean 定义并实例化 bean,会继续向下调用refresh内部的refresh()
		//下方示例中就省略了直接到我们最终的refresh()
        this.refresh(context);
        if (this.registerShutdownHook) {
            try {
                context.registerShutdownHook();
            } catch (AccessControlException var3) {
            }
        }

    }
public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
        	//激活开启容器
            this.prepareRefresh();
            //获取 bean 工厂,默认会返回DefaultListableBeanFactory类型的bean工厂
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            //对获取到的 beanFactory 做预处理设置
            this.prepareBeanFactory(beanFactory);

            try {
            	//beanFactory准备工作完成后进行的后置处理工作
                this.postProcessBeanFactory(beanFactory);
                //执行 beanFactory 后置处理器的方法
                this.invokeBeanFactoryPostProcessors(beanFactory);
                //注册 bean 的后置处理器
                this.registerBeanPostProcessors(beanFactory);
                //初始化 MessageSource 组件
                this.initMessageSource();
                //初始化事件派发器,多播器
                this.initApplicationEventMulticaster();
                //用来初始化子容器中的bean,默认是空方法
                this.onRefresh();
                //注册监听器
                this.registerListeners();
                //初始化所有剩下的单实例 bean
                this.finishBeanFactoryInitialization(beanFactory);
                //完成ben的创建初始化工作,完成 IOC 容器的创建
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }

2. refresh—>obtainFreshBeanFactory() bean工厂BeanFactory或BeanDefinitionRegistry与BeanDefinition xml解析器 XmlBeanDefinitionReade相关

  1. 首先在服务启动时会获取指定bean的class,扫描转换为BeanDefinition,这些BeanDefinition是如何管理的,服务启动继续执行会将这些根据这些BeanDefinition创建出实例bean,如何创建的,创建过程中或创建完成后是如何管理的
  2. refresh中调用了obtainFreshBeanFactory()方法,该方法中重点关注调用的refreshBeanFactory()方法,刷新bean工厂,默认创建一个 DefaultListableBeanFactory类型的 bean工厂,而DefaultListableBeanFactory继承了BeanFactory,并且实现了BeanDefinitionRegistry所以DefaultListableBeanFactory除了是个管理bean的bean工厂以外,还管理了解析到的BeanDefinition
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        this.refreshBeanFactory();
        return this.getBeanFactory();
    }

	protected final void refreshBeanFactory() throws BeansException {
        if (this.hasBeanFactory()) {
            this.destroyBeans();
            this.closeBeanFactory();
        }

        try {
        	//1.创建bean工厂
            DefaultListableBeanFactory beanFactory = this.createBeanFactory();
            beanFactory.setSerializationId(this.getId());
            this.customizeBeanFactory(beanFactory);
            //创建xml文件读取器
            this.loadBeanDefinitions(beanFactory);
            synchronized(this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        } catch (IOException var5) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
        }
    }
  1. 在refreshBeanFactory()中创建BeanFactory完毕后,会执行一个loadBeanDefinitions(),通过这个方法创建了xml文件读取器,也就BeanDefinition xml解析器XmlBeanDefinitionReader
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        //用来解析xml中配置的bean
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
     beanDefinitionReader.setEnvironment(this.getEnvironment());        
      beanDefinitionReader.setResourceLoader(this);
       beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
       initBeanDefinitionReader(beanDefinitionReader);
    	//这里才是核心,加载beanDefinition的工作还没开始
        loadBeanDefinitions(beanDefinitionReader);
    }
  1. 当XmlBeanDefinitionReader创建完毕后会调用loadBeanDefinitions()—>doLoadBeanDefinitions(),解析xml生成Document对象,调用registerBeanDefinitions()
	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
		// 1.根据inputSource和resource加载XML文件,并封装成Document
        Document doc = doLoadDocument(inputSource, resource);
     //注册BeanDefinition
        return registerBeanDefinitions(doc, resource);    
    }
  1. registerBeanDefinitions()向下链路比较深
  1. 实例化BeanDefinitionDocumentReader
  2. 调用registerBeanDefinitions()解析并注册BeanDefinition
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    // 1.使用DefaultBeanDefinitionDocumentReader实例化BeanDefinitionDocumentReader
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    // 2.记录统计前BeanDefinition的加载个数
    int countBefore = getRegistry().getBeanDefinitionCount();
    // 3.createReaderContext:根据resource创建一个XmlReaderContext
    // 4.registerBeanDefinitions:加载及注册Bean定义
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    // 5.返回本次加载的BeanDefinition个数
    return getRegistry().getBeanDefinitionCount() - countBefore;
}
  1. 查看registerBeanDefinitions()内部是怎么解析注册的
  1. 会基于Document拿到xml中配置的bean的节点信息
  2. 最终会调用到parseBeanDefinitions(), bean 定义的核心部分,遍历 root 节点(正常为 < beans> 节点)下的所有子节点,对子节点进行解析处理,如果节点的命名空间是 spring 默认的命名空间,则走 parseDefaultElement(ele, delegate) 方法进行解析,例如最常见的:< bean>, 如果节点的命名空间不是 spring默认的命名空间,也就是自定义命名空间,则走 delegate.parseCustomElement(ele) 方法进行解析,例如常见的: < context:component-scan/>、< aop:aspectj-autoproxy/>
    默认的命名空间为:http://www.springframework.org/schema/beans,其他都是自定义命名空间,例如 aop 的命名空间为:http://www.springframework.org/schema/aop
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    logger.debug("Loading bean definitions");
    // 1.拿到文档的子节点,对于Spring的配置文件来说,理论上应该都是<beans>
    Element root = doc.getDocumentElement();
    // 2.通过拿到的节点,注册 Bean 定义
    doRegisterBeanDefinitions(root);
}

protected void doRegisterBeanDefinitions(Element root) {
    BeanDefinitionParserDelegate parent = this.delegate;
    // 构建BeanDefinitionParserDelegate
    this.delegate = createDelegate(getReaderContext(), root, parent);
 
    // 1.校验root节点的命名空间是否为默认的命名空间(默认命名空间http://www.springframework.org/schema/beans)
    if (this.delegate.isDefaultNamespace(root)) {
        // 2.处理profile属性
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
        if (StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                    profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            // 校验当前节点的 profile 是否符合当前环境定义的, 如果不是则直接跳过, 不解析该节点下的内容
            if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                if (logger.isInfoEnabled()) {
                    logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                            "] not matching: " + getReaderContext().getResource());
                }
                return;
            }
        }
    }
    // 3.解析前处理, 留给子类实现
    preProcessXml(root);
    // 4.解析并注册bean定义
    parseBeanDefinitions(root, this.delegate);
    // 5.解析后处理, 留给子类实现
    postProcessXml(root);
 
    this.delegate = parent;
}

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    // 1.默认命名空间的处理
    if (delegate.isDefaultNamespace(root)) {
        NodeList nl = root.getChildNodes();
        // 遍历root的子节点列表
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                if (delegate.isDefaultNamespace(ele)) {
                    // 1.1 默认命名空间节点的处理,例如: <bean id="test" class="" />
                    parseDefaultElement(ele, delegate);
                }
                else {
                    // 1.2 自定义命名空间节点的处理,例如:<context:component-scan/>、<aop:aspectj-autoproxy/>
                    delegate.parseCustomElement(ele);
                }
            }
        }
    } else {
        // 2.自定义命名空间的处理
        delegate.parseCustomElement(root);
    }
}

3. refresh()—>invokeBeanFactoryPostProcessors() bean工厂后置处理器BeanFactoryPostProcessor的创建与执行

  1. Spring中创建bean的顺序是有优先级的,在BeanFactory创建完后后会进行一些处理,并且在BeanFactory创建完后后说明要接下来要开始初始化创建其它的bean了,要进行一些预处理,所以提供了BeanFactoryPostProcessor,在BeanFactory创建完成,bean转换为BeanDefinition后,通过refresh()中的invokeBeanFactoryPostProcessors()获取BeanFactoryPostProcessor,执行它的postProcessBeanFactory()方法实现这些预处理功能
  2. Spring中提供了多个直接或间接实现了BeanFactoryPostProcessor的类,以基于注解注入来说,在启动服务创建针对注解的BeanDefinition解析器AnnotatedBeanDefinitionReader时,会创建一系列的BeanFactoryPostProcessor,BeanPostProcessor的BeanDefinition,其中就有ConfigurationClassPostProcessor间接继承了BeanFactoryPostProcessor,通过invokeBeanFactoryPostProcessors()的执行优先将这个bean创建注入,那么在创建其它bean时就可以获取到这个bean,处理不管是手动注册还是扫描机制所有BeanDefinition中符合注解条件的BeanDefinition,过滤出带有相关注解的BeanDefinition包括(@Configuration、@Component、@ComponentScan、@Import、@ImportResource或者@Bean)进行进一步处理
  3. 查看invokeBeanFactoryPostProcessors()源码,内部会调用PostProcessorRegistrationDelegate下的invokeBeanFactoryPostProcessors()静态方法,该方法中首先会获取已有的BeanFactoryPostProcessor执行它的postProcessBeanFactory(),执行完毕后,会通过BeanFactory获取实现了BeanFactoryPostProcessor 接口的所有 Bean 名称,然后通过bean名称获取到对应的BeanDefinition,调用beanFactory的getBean()方法进行初始化创建拿到对象实例,然后执行它的postProcessBeanFactory()方法(查看源码实际上是比较复杂的,有很多判断,还有创建顺序什么的,省略掉一些其它代码,针对BeanFactoryPostProcessor的创建执行就以下几行,)
public static void invokeBeanFactoryPostProcessors(
	//1.获取以及存在的BeanFactoryPostProcessor,执行它的postProcessBeanFactory()方法
	//......
	
    //2.获取所有实现了 BeanFactoryPostProcessor 接口的 Bean 名称
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    
    // 执行 BeanFactoryPostProcessor
    for (String postProcessorName : postProcessorNames) {
        // 获取对应的 BeanFactoryPostProcessor 实例
        BeanFactoryPostProcessor postProcessor = beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class);
        // 调用 postProcessBeanFactory() 方法
        postProcessor.postProcessBeanFactory(beanFactory);
    }
}

4. refresh()—>registerBeanPostProcessors() bean后置处理器的创建

  1. 在服务启动时创建ApplicationContext后会创建BeanDefinition 注解解析器AnnotatedBeanDefinitionReader,通过这个注解解析器会创建一系列BeanFactoryPostProcessor,BeanPostProcessor,前面已经讲了ConfigurationClassPostProcessor是一个BeanFactoryPostProcessor,另外还有BeanPostProcessor比如
  1. 用来支持 @Autowired @Value 等注解的解析AutowiredAnnotationBeanPostProcessor
  2. 可以处理@PostConstruct和@PreDestroy还有@Resource等注解的CommonAnnotationBeanPostProcessor
  3. 用来支持JPA的PersistenceAnnotationBeanPostProcessor
  1. 另外还有比如支持aop的AnnotationAwareAspectJAutoProxyCreator 在使用aop是需要通过@EnableAspectJAutoProxy开启aop功能,通过这个注解最重要的是向容器中添加了AnnotationAwareAspectJAutoProxyCreator ,该类间接继承了 BeanFactoryAware与BeanPostProcessor接口,在创建其它bean对象时,判断如果需要aop增强,则通过AnnotationAwareAspectJAutoProxyCreator 重写的BeanPostProcessor中的postProcessAfterInitialization创建代理类
  2. 也就是BeanPostProcessor要先一步创建,通过它来监听其它bean的创建,在创建其它bean对象时,通过BeanPostProcessor中的postProcessBeforeInitialization()方法,和postProcessAfterInitialization()方法,对监控到的bean对象进行特殊处理
  3. 那BeanPostProcessor是怎么先一步创建的,就是在这里registerBeanPostProcessors()中创建出来的,简单看一下源码:
  1. 调用beanFactory的getBeanNamesForType()方法获取到所有实现了BeanPostProcessor接口的类名称
  2. 遍历获取到的这些bean名称,将这些BeanPostProcessor进行分类,例如:实现了 PriorityOrdered 的放入priorityOrderedPostProcessors集合中,实现了PriorityOrdered 并且是MergedBeanDefinitionPostProcessor类型的放入internalPostProcessors,实现了 Ordered 的放入 orderedPostProcessorNames 集合中,否则放入 nonOrderedPostProcessorNames 集合中
  3. 然后遍历这些BeanPostProcessor名称,执行beanFactory的getBean()方法获取到bean对象,调用beanFactory的addBeanPostProcessor()将这个BeanPostProcessor对象添加到beanFactory的beanPostProcessors属性中

5. refresh()—>initApplicationEventMulticaster() 初始化事件派发器,多播器

  1. 该方法中没有什么特殊的操作,只是用来初始化实际派发器,多播器,在后面事件驱动模型开发时使用,该方法中首先判断容器中是否存在id为"applicationEventMulticaster"的事件派发器,如果没有则创建一个类型为SimpleApplicationEventMulticaster事件派发器,设置到BeanFactory的applicationEventMulticaster属性上,并以"applicationEventMulticaster"为id添加到singletonObjects中
  2. 这里注册的applicationEventMulticaster事件派发器要与下面refresh()—>registerListeners()监听器的注册放到一块来看

6. refresh()—> this.onRefresh() 用来初始化子容器中的bean,默认是空方法

可以提供子类重写这个方法,在容器刷新时,做些其它扩展操作

7. refresh()—>this.registerListeners() 注册监听器

  1. 该方法中首先会调用getBeanNamesForType(ApplicationListener.class, true, false)获取到类型为ApplicationListener所有监听器的名字
  2. 遍历获取到的监听器名称,通过beanFactory获取到前面注册的applicationEventMulticaster事件派发器,调用派发器的addApplicationListenerBean()方法,将监听器名称,注意是名称添加到事件派发器中
  3. 然后会获取之前注册的事件earlyApplicationEvents,如果不为空遍历这些事件调用applicationEventMulticaster事件派发器的广播事件方法multicastEvent()将这些事件广播出去,问题:这里执行了之前注册的事件,那么之后注册的事件如何执行,这里要结合refresh()—>finishRefresh() 去理解
protected void registerListeners() {
	//获取的是成员applicationListeners
	for (ApplicationListener<?> listener : getApplicationListeners()) {
	// 获取SimpleApplicationEventMulticaster触发其方法
		getApplicationEventMulticaster().addApplicationListener(listener);
	}

	// 从容器中获取ApplicationListener
	String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
	for (String listenerBeanName : listenerBeanNames) {
		// 获取SimpleApplicationEventMulticaster触发其方法-这里放的是beanName
		getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
	}

	// 发布早期事件,本文这里为空
	Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;

	//设置为null,这个很重要
	this.earlyApplicationEvents = null;
	if (earlyEventsToProcess != null) {
	// 如果早期/渴望的事件存在,则将其广播出去
		for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
			getApplicationEventMulticaster().multicastEvent(earlyEvent);
		}
	}
}

//SimpleApplicationEventMulticaster 事件派发器中,广播事件方法示例
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
        ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
        //获取所有通过发布的事件对象获取对应的 ApplicationListener 监听器
        Iterator var4 = this.getApplicationListeners(event, type).iterator();
		//遍历获取到的监听器
        while(var4.hasNext()) {
            final ApplicationListener<?> listener = (ApplicationListener)var4.next();
            Executor executor = this.getTaskExecutor();
            //判断是否可以异步执行,如果可以则使用多线程方式进行异步执行
            if (executor != null) {
            	//多线程方式异步执行
                executor.execute(new Runnable() {
                    public void run() {
                        SimpleApplicationEventMulticaster.this.invokeListener(listener, event);
                    }
                });
            } else {
            	//同步执行
                this.invokeListener(listener, event);
            }
        }
    }

8. refresh()—>finishBeanFactoryInitialization()与beanFactory.getBean()引出bean的创建,是怎么由BeanDefinition实例化为bean的

  1. beanFactory的getBean()方法会在多个位置调用,比如在invokeBeanFactoryPostProcessors()创建BeanFactoryPostProcessor或registerBeanPostProcessors()BeanPostProcessor时中都调用了该方法,该方法时创建bean对象的入口
  2. finishBeanFactoryInitialization()初始化所有剩下的单实例 bean时,方法内会获取到一个ConfigurableListableBeanFactory 类型的对象beanFactory,通过这个对象默认调用它的实现子类 DefaultListableBeanFactory 中的 preInstantiateSingletons()方法
    ,该方法中会通过 while 循环调用AbstractBeanFactory的 getBean(beanName)方法, 在 getBean() 方法中调用 doGetBean() 方法中会通过 getSingleton() 方法去获取 bean, 如果首次执行时,没有这个 bean, 则调用AbstractAutowireCapableBeanFactory 子类实现的 createBean() 方法,在createBean()方法中通过调用 doCreateBean()
  3. 注意: 在createBean()或doCreateBean()方法进行实际创建前首先会调用resolveBeforeInstantiation(beanName, mbdToUse) 通过后置处理器,创建当前 ben 的代理对象返回(动态代理,在AOP中有详细讲解)
  4. createBean()整个调用链路很长,此处就先简单描述一下,查看doCreateBean()源码:
  1. 通过 getSingleton() 方法通过singletonObjects一级缓存获取 bean, 如果首次执行时,没有这个 bean, 则调用createBean() 创建这个 bean, 当这个bean创建初始化完成以后,会将这个bean放入 singletonObjects 集合中
  2. 在createBean()中首先调用"getMergedLocalBeanDefinition(beanName)"通过mergedBeanDefinitions根据当前bean的名称获取到对应的BeanDefinition(mergedBeanDefinitions 存储的是经过合并和解析后的 BeanDefinition),然后调用resolveBeforeInstantiation(beanName, mbdToUse) 尝试通过后置处理器,创建当前 ben 的代理对象返回,也就是动态代理,比如aop参考前面的笔记: Spring AOP 的搭建与源码分析
  3. 如果没有创建出代理类createBean()继续向下执行最终会调用到createBeanInstance()通过BeanDefinition利用反射等功能创建bean实例
  1. 查看createBeanInstance()源码:
  1. 首先会通过BeanDefinition中读取到的定义信息进行一系列的校验,例如是否是public权限
  2. 通过BeanDefinition判断能否通过回调方法创建当前获取的bean,例如FactoryBean的getObject()
  3. 判断当前bean构造器是否需要入参等,调用autowireConstructor()或instantiateBean()基于BeanDefinition创建出实例bean并返回
  4. 参考博客
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		// 确认需要创建的bean实例的类可以实例化
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		// 确保class不为空,并且访问权限是public
		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

		// 判断当前beanDefinition中是否包含实例供应器,此处相当于一个回调方法,利用回调方法来创建bean
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		// 如果工厂方法不为空则使用工厂方法初始化策略
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// 一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器
		// 在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析

		// Shortcut when re-creating the same bean...
		// 标记下,防止重复创建同一个bean
		boolean resolved = false;
		// 是否需要自动装配
		boolean autowireNecessary = false;
		// 如果没有参数
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				// 因为一个类可能由多个构造函数,所以需要根据配置文件中配置的参数或传入的参数来确定最终调用的构造函数。
				// 因为判断过程会比较,所以spring会将解析、确定好的构造函数缓存到BeanDefinition中的resolvedConstructorOrFactoryMethod字段中。
				// 在下次创建相同时直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存的值获取,避免再次解析
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		// 有构造参数的或者工厂方法
		if (resolved) {
			// 构造器有参数
			if (autowireNecessary) {
				// 构造函数自动注入
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				// 使用默认构造函数构造
				return instantiateBean(beanName, mbd);
			}
		}

		// Candidate constructors for autowiring?
		// 从bean后置处理器中为自动装配寻找构造方法, 有且仅有一个有参构造或者有且仅有@Autowired注解构造
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		// 以下情况符合其一即可进入
		// 1、存在可选构造方法
		// 2、自动装配模型为构造函数自动装配
		// 3、给BeanDefinition中设置了构造参数值
		// 4、有参与构造函数参数列表的参数
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// Preferred constructors for default construction?
		// 找出最合适的默认构造方法
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			// 构造函数自动注入
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		// No special handling: simply use no-arg constructor.
		// 使用默认无参构造函数创建对象,如果没有无参构造且存在多个有参构造且没有@AutoWired注解构造,会报错
		return instantiateBean(beanName, mbd);
	}
  1. doCreateBean() 方法中首先调用会调用 populateBean() 方法, 对创建的 bean 的属性赋值 ,然后调用 initializeBean() 方法,执行创建这个 bean 的初始化方法
  2. initializeBean() 方法中先后调用了三个主要的方法 :
    • applyBeanPostProcessorsBeforeInitialization() 执行初始化前的方法,
    • invokeInitMethods() 执行初始化方法,例如我们自定义的一些初始化方法,框架中定义的一些初始化方法
    • applyBeanPostProcessorsAfterInitialization() 执行初始化后的方法
    • 初始化前后的方法执行,主要是判断需要初始化的bean是否是 BeanPostProcessor 的实现子类,如果是,在初始化前,调用执行 postProcessBeforeInitialization() 方法, 在初始化后,调用执行 postProcessAfterInitialization() 方法

9. refresh()—>this.finishRefresh() 完成ben的创建初始化工作,完成 IOC 容器的创建,发布容器刷新完成事件

protected void finishRefresh() {
		//初始化跟生命周期有关的后置处理器,在容器中获取LifecycleProcessor
		//类型的后置处理器接口,在容器刷新完成以及关闭时执行的方法,此处是注册
		//如果没有会注册一个默认的生命周期组件
        this.initLifecycleProcessor();
        //拿到生命周期处理器,回调onRefresh()容器刷新完成方法,
        this.getLifecycleProcessor().onRefresh();
        //推送上下文刷新完毕事件到相应的监听器
        this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this)));
        LiveBeansView.registerApplicationContext(this);
    }

  1. 当前终点关注内部调用的publishEvent()推送上下文刷新完毕事件到相应的监听器
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
        Assert.notNull(event, "Event must not be null");
        // 1.如有必要,将事件装饰为ApplicationEvent
        ApplicationEvent applicationEvent;
        if (event instanceof ApplicationEvent) {
            applicationEvent = (ApplicationEvent) event;
        }else {
            applicationEvent = new PayloadApplicationEvent<>(this, event);
            if (eventType == null) {
                eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
            }
        }

        if (this.earlyApplicationEvents != null) {
            this.earlyApplicationEvents.add(applicationEvent);
        }
        else {
            // 2.使用事件广播器广播事件到相应的监听器
            getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
        }

       
        // 3.同样的,通过parent发布事件.....
        if (this.parent != null) {
            if (this.parent instanceof AbstractApplicationContext) {
                ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
            }
            else {
                this.parent.publishEvent(event);
            }
        }
    }

10. 概述 Spring 启动refresh()方法执行bean的状态流转过程

  1. 也是就是上面说的启动Spring IOC注入过程: BeanFactory—>BeanFactoryPostProcessor —> BeanPostProcessor—>其它bean
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

11. Bean的生产顺序是由什么决定的,BeanDefinition的注册顺序是由什么决定的

  1. 首先bean的创建顺序是由BeanDefinition的注册顺序决定的,依赖关系也会影响bean的创建顺序
  2. BeanDefinition的注册顺序是由什么来决定的: 是由配置或使用的@那种注解来决定,是由解析顺序来决定的
  3. BeanDefinition解析注解的顺序依次: @Configuration, @Component, @Impotr, @Bean, @ImportBeanDefinitionRegistrar,其中内部还有很多其它细节,例如当多个@Component时,可以通过@Order去影响多个@Component的解析顺序等等
  4. 假设通过@Configuration, @Component, @Impotr, @Bean, @ImportBeanDefinitionRegistrar等不同方式向容器中注入相同beanName的bean,根据BeanDefinition解析顺序,后面的会覆盖前面的
  5. 还有其它几种复杂情况:
  1. @Import 与@Configuration:通过@Import导入了一个配置类此时的顺序是:普通@Configuration—>@Import 与@Configuration组合—>@Component, @Impotr, @Bean, @ImportBeanDefinitionRegistrar
  2. @Import 与@Bean: 通过@Import 导入了一个配置类配置类中有@Bean此时这个组合出来的@Bean的顺序是: 在@Impotr后 @Bean前
  3. 另外@ImportBeanDefinitionRegistrar是向容器中手动注入BeanDefinitionRegistrar解析器的方式,所以是最后执行
    还有一种情况,假设一个类使用@Component修饰,但是该类又实现了BeanDefinitionRegistryPostProcessor接口,此时该类的执行顺序: 会在@Component这个级别执行,但是多个@Component时又会按照类的不同类型,@Order等等再次排序加载

12. 怎么给Spring做扩展

Spring IOC过程中有哪些扩展点

  1. Spring在启动时提供了很多扩展接口,提供了钩子方法供用户实现,提供附加功能
  2. 在启动Spring容器时先调用obtainFreshBeanFactory() 创建DefaultListableBeanFactoryB,然后执行invokeBeanFactoryPostProcessors(beanFactory),通过该方法执行的创建bean工厂后的扩展点
  1. BeanDefinitionRegistryPostProcessor —> postProcessBeanDefinitionRegistry() 动态的去注册BeanDefinition
  2. BeanFactoryPostProcessor —> postProcessBeanFactory()
  1. BeanPostProcessor 中的两个抽象方法,在创建bean完成后,执行populateBean()方法对属性赋值,通过执行initializeBean(),初始化bean后的扩展点 (Spring中提供了多种后置处理器,最起码要说出这个初始化前后的)

BeanPostProcessor —> 初始化前: postProcessBeforeInitialization(), 初始化后: postProcessAfterInitialization()

  1. 另外还对象初始化前后,销毁前后执行的init-method,destroy-method方法

如何在所有BeanDefinition注册完成后做扩展

  1. Spring提供了BeanFactoryPostPropersser,内部有postProcesserBeanFactory(),在BeanDefinition注册完成后,可以通过beanFactory调用getBeanDefinitionNames()获取到容器中所有的BeanDefinition 名称,然后通过这个名称可以获取到所有BeanDefinition,进行指定操作,并且Spring在启动时创建BeanFactory后,会通过invokeDifinitionRegistryPostProcessor()方法先执行BeanDefinition相关bean的操作,在然后执行BeanFactoryPostPropersser下的postProcesserBeanFactory()方法, 该方法就可以看为是所有BeanDefinition注册完成后的扩展点

如何在所有的bean创建完成后做扩展

  1. Spring启动按顺序创建为指定类型bean后,会执行finishBeanFactoryInitialization方法,获取到所有的BeanDefinition,通过beanFactory.getBean()创建其它的单实例bean,该方法执行完毕后所有bean才创建完毕
  2. 在bean创建完成后,遍历bean,判断是否是SmartInitializingSingleton类型,如果是执行该类下的afterSingletonsInstantiated()方法,该方法就是所有bean创建完成后的扩展点
  3. 另外,在refresh()下,执行finishBeanFactoryInitialization()完毕后,还会执行一个finishRefresh()方法,在该方法中会执行一个publishEvent(new ContextRefreshedEvent(this)),通过该方法发布事件,可以通过事件监听机制,EventListener监听到ContextRefreshedEvent事件进行扩展,也是一个扩展点

四. 其它问题总结

1. BeanDefinitionRegistry的注册

  1. 我们定义bean时不管是通过java config方式,还是xml配置文件的方式,最终都会解析成BeanDefinition,而这些BeanDefinition都需要注册到容器中,这个注册的过程是通过接口org.springframework.beans.factory.support.BeanDefinitionRegistry来完成的
  2. BeanDefinitionRegistry 是一个接口,定义了关于 BeanDefinition 的注册、移除、查询等一系列的操作,该接口有三个实现类:DefaultListableBeanFactory、GenericApplicationContext、SimpleBeanDefinitionRegistry,在项目启动时默认使用的是DefaultListableBeanFactory
  3. DefaultListableBeanFactory中通过成员变量。来保存所以的beanDefinition
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
  1. DefaultListableBeanFactory除了实现BeanDefinitionRegistry 接口,还实现了BeanFactory接口,提供了基本的BeanFactory功能,默认情况下Spring启动,创建的BeanFactory工厂就是DefaultListableBeanFactory
  1. 通过实现BeanDefinitionRegistry接口:实现了对 BeanDefinition 的注册、移除、查询等一系列的操作。
  2. 通过实现BeanFactory接口: 变为了Bean工厂的默认实现,提供了bean的实例化、定位、配置应用程序中的对象及建立这些对象间的依赖能力

2. Spring 实例化bean有几种方式

  1. 大概有四种方式:
  1. 利用反射调用构造器实例化: 以Spring xml配置bean举例,需要配置该bean的class属性为该bean的路径,在Spring启动时,通过BeanDifinition读取class属性指向的路径,然后通过反射根据这个类路径调用构造器,进行实例化
  2. 静态工厂方式,配置bean的factory-method工厂静态方法,通过这个静态工厂方法返回实例对象
  3. 实例工厂方式例如@Bean: 在factory-method静态工厂的基础上,指定一个factory-bean工厂bean,底层在实例化时会调用指定工厂中的factory-method, 而@Bean底层就是通过该方式实现的,在使用@Configuration+@Bean注解时,会将@Bean所在的配置类读取到BeanDefinition的factoryBeanName属性中,会将@Bean修饰的方法名读取到BeanDefinition的factoryMethodName中
  4. FactoryBean方式,实现FactoryBean接口重写getObject()方法,该方式创建对象是懒加载
  1. 有什么不同: 1是由Spring去控制创建处理,2,3,4可以通过编码的方式自己控制实例化的过程更灵活

3. Spring有哪几种配置方式

  1. 也就是怎么给Spring容器配置元数据
  1. XML配置: Spring.xml,配置< bean>标签等
  2. 注解配置: Spring2.5+提出, 基于注解例如配置中使用< component-scan> 开启包扫描,基于包扫描,与注解进行注入
  3. java配置: 又被称为javaConfig,Spring3.0后提出:@Configuration, @Bean,@PropertySource, @Value, @ComponentScan

4. bean的配置方式

  1. xml方式,通过bean标签配置
  2. @Component方式: (@Controller,@Service, @Repostory…)前提: 需要配置包扫描@ComponentScan,该方式底层是通过反射调用构造方法创建的
  3. @Bean方式:通常用来修饰方法与@Configuration配合使用,可以自己控制实例化过程
  4. @Impot方式: @ImportSelectot返回一个对象数组,@ImportBeanDefinitionRegistrar提供了一个BeanDefinition注册器,可以动态的去注入
  1. 对应读取XML有XmlBeanDefinitionReader实现子类, 对应读取javaConfig的有AnnotatedBeanDefinitionReader实现子类
  1. javaconfing方式: 在创建Spring容器,调用refresh()注入bean前,会先执行一个register(),该方法中会执一个"reader.register(anotatedClasses);"方法,通过AnnotatedBeanDefinitionReader读取项目中的配置类也就是配置类相关注解
  2. xml方式:是在refresh()方法中,会执行一个obtainFreshBeanFactory(),该方法中会执行refreshBeanFactory()—>loadBeanDefinitions(beanFactory)在该方中通过XmlBeanDefinitionReader读取xml,进行读取
  1. 解析阶段: 最终会解析xml中的节点,或javaConfiguration中的配置类到BeanDefinition
  1. 对应javaConfig使用ConfigurationClassParser 配置类解析器—>doProcessConfigurationClass()该方法中会解析@PropertySource,@ComponentScan, @Import, @Bean…等注解注册为BeanDefinition
  2. 对应xml使用DefaultBeanDefinitionDocumentReader---->parseDefaultElement()方法解析xml中各种节点,注册为BeanDefinition
  1. 读取解析到bean信息后,将解析到的bean的路径保存到BeanDefinition的class属性,bean的模式保存到scope属性属性中,bean属性的初始化值保存到property中…,最终将得到的BeanDefinition存储到beanDefinitionMap中,在创作该bean时,Spring底层会通过这个BeanDefinition拿到这些配置信息,然后通过BeanFactory创建这个bean
  2. 后续创建bean时跟还是Spring启动IOC注入的流程,创建BeanFactory,加载所有BeanDefinition,通过BeanFactory.getBean()–>createBean()–>通过beanName在beanDefinitionMap中获取到对应的BeanDefinition,拿到这个bean的class属性也就是路径,通过反射调用构造器创建…
  3. 怎么解析@Bean, @Import, @ComponentScan, @Component…修饰的bean到beanDefinitionMap的,Spring提供了ConfigurationClassParser,会执行该类下的doProcessConfigurationClass()方法,扫描对应的注解,进行解析
  4. 那ConfigurationClassParser怎么扫描的,以 @ComponentScan 为例Spring提供了ClassPathBeanDefinitionSacnner通过该类下的doScan()方法扫描,根据包路径找到所有的.class文件,判断类是不是标准的@Component注解,判断是不是接口,是不是抽象类…
  5. 那么BeanDefinition是在哪一步读取进入的呢: 是在invokeDifinitionRegistryPostProcessor()

5. @ComponentScan不设置basePackage为什么也会包扫描

Spring底层在解析@ComponentScan时,如果没有设置basePackage值,默认会拿@ComponentScan所在类所在的包的地址,扫描该地址下的

6. javaConfig如何代替spring.xml的

  1. java配置又被称为javaConfig,Spring3.0后提出,通过注解配置类来代替以前的Spring.xml配置文件
  2. 例如使用@Config修饰配置类,通过这个配置类代替以前的Spring.mxl,向容器中注入bean时,@Bean代替了Spring.xml的< bean> 标签,其它还有@Scope, @Lazy,包扫描的@ComponentScan, 读取配置文件的@PropertySource,@Value…
  1. 在Spring.xml时,Spring容器提供了ClassPathXmlApplicationContext上下文
  2. javaConfig时: Spring容器提供了AnnotationConfigApplicationContext上下文

7. @Component,@Controller,@Repository,@Service有什么区别

  1. 首先@Component是@Controller,@Repository,@Service的元注解,也可以将后面三个统一看为是@Component
  2. 那么为什么要分出四个来:让代码的阅读性更好,@Controller标注控制器,@Service标注业务逻辑层,@Repository标注数据访问层

8. @Import有几种使用方式

仔细来说的话应该有四种

  1. 使用@Import直接导入一个类
  2. 导入一个实现了ImportSelector接口的类,重写的selectImports()方法,返回一个存储类路径的数组,@Import在注入时会执行该方法,注入方法返回的数组中的类路径指定的bean,因为是数组可以一次注册多个bean
  3. 导入一个实现了ImportBeanDefinitionRegistrar接口的类,重写registerBeanDefinitions(),通过执行该方法向容器中注入bean,注意点,该方式使用的是BeanDefinitionRegistry注册器方式注入,需要自己先创建一个BeanDefinition,由于是注册器方式注册,该方式注册的bean的
  4. 另外查看第2中方式ImportSelector接口下还存在一个子接口DeferredImportSelector,使用@Import导入实现了该接口的类也可以,注意点SpringBoot的自动配置就是使用的该方式,特点是与注册时机晚于ImportSelector,并且具有延迟,分组的特性

9. @Configuration的作用及原理解析

  1. Spring3.0后提出的基于javaConfig方式,使用注解配置中的其中一个注解,也可代替Spring.xml配置文件,实际这样说并不太标准,通常情况下使用@Configuration+@Bean向容器中配置bean,但是只是用@Bean实际也可以注入bean的
  2. 那么在向Spring中配置bean时,加@Configuration与不加有什么区别:加了@Configuration会为配置类创建cglib动态代理,用来保证内部被@Bean修饰的方法创建的bean是单例的,例如:
  1. 通过@Bean修饰方法1,方法1内部new了一个a对象注入到了容器中
  2. 通过@Bean修饰方法2,在该方法手动调用了两次方法1,
  3. 方法2中两次调用方法1,相当于new了两次a对象,就会出现多例的情况
  4. 使用@Configuration后,在方法2调用方法1时,会带来增强,会先在IOC容器中获取,获取不到再去创建
  1. 原理: 在启动Spring容器时会创建ApplicationConfigApplicationContext,在执行refresh()方法前会调用一个this()无参构造器,在构造器中会new一个new AnnotatedBeanDefinitionReader(this),在这里面会创建用于支撑整个SpringIOC加载的内部组件,其中就包括ConfigurationClassPostProcessor,用来解析@Configuration注解的后置处理器
  2. ConfigurationClassPostProcessor 中重点关注实现的BeanFactoryPostProcess与BeanDefinitionRegistryPostProcessor两个接口, 在Spring启动时通过执行refresh()方法中的invokeBeanFactoryPostProcessor():
  1. 执行ConfigurationClassPostProcessor重写的BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry()方法,解析@Configuration, @Bean, @Import, @Component…等注解,注册为BeanDefinition
  2. 执行ConfigurationClassPostProcessor重写的BeanFactoryPostProcess中的postProcessBeanFactory()方法,创建cglib动态代理
  3. 通过动态代理对配置类方法代理增强,例如增强配置类中@Bean修饰的方法,在通过该方法创建对象时先去容器中查询,查询不到才创建

10. @Bean修饰的方法的调用是怎么保证单例的

  1. 先解释一下@Bean修饰的方法为什么会出现不是是多例的情况: @Bean方法中new对象,然后手动多次调用,而不是通过容器去获取就会出现多例的情况,
  2. 怎么保证单例: 可以查看上方的"@Configuration的作用及原理解析", 就是通过@Configuration修饰@Bean方法所在的类,在Spring启动时底层会对@Configuration修饰的类进行代理增强,当手动调用@Bean修饰的方法,获取bean时,会先去容器中查找,如果查找不到再创建

11. 如何将一个三方的类配置为Bean

  1. 这个问题的意思是一个三方类,我们无法修改这个类,例如在类上使用注解注入为Bean到容器中,
  2. 那么可以如何导入:
  1. @Import(三种),
  2. @Bean
  3. 实现BeanDefinitionRegistryPostProcessor接口,通过重写方法,以DefinitionRegistry注册器方式…

12. 什么是bean的装配, 什么是bean的自动装配

  1. 装配,就是依赖注入,以Spring xml配置bean为例,假设当前配置的bean需要一个属性,我们可以通过property属性设置这个属性值,这个方式我们称为手动装配
  2. 那么什么是自动装配,例如使用@Autowired,@Resource注解,自动的在容器中获取需要注入的bean进行注入,这个称为自动注入

13. Spring 容器启动时为什么先加载BeanFactoryPostProcess

  1. 首先Spring启动时先创建BeanFactory,然后执行invokeBeanFactoryPostProcessors(beanFactory) ,在该方法中会加载所有的BeanDefinition,读取所有bean的配置信息,而BeanFactoryPostProcess中提供了一个postProcessBeanFactory(), 是在所有BeanDefinition都加载完成后执行的,可以看为是所有BeanDefinition注册完成后的的扩展,然后通过BeanDefinition创建实际的bean对象
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值