进行spring源码分析时,可以写个测试类,一步一步往下调试
测试类如下:
package com.wangcongming.demo;
import com.wangcongming.demo.config.AppConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @program: spring
* @description: 测试
* @author: wang congming
* @create: 2019-12-10 20:18
*/
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
}
}
package com.wangcongming.demo.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @program: spring
* @description:
* @author: wang congming
* @create: 2019-12-14 21:12
*/
@Configuration
@ComponentScan("com.wangcongming.demo")
public class AppConfig {
}
package com.wangcongming.demo.service;
import org.springframework.stereotype.Service;
/**
* @program: spring
* @description:
* @author: wang congming
* @create: 2019-12-11 20:28
*/
@Service
public class UserService {
public UserService() {
System.out.println("userService con");
}
public void query(){
System.out.println("query");
}
}
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.PostProcessorRegistrationDelegate;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.annotation.ConfigurationClassParser;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.context.annotation.ComponentScanAnnotationParser;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
//1. spring容器初始化时,会先调用父类的构造方法,实例化一个工厂 DefaultListableBeanFactory
GenericApplicationContext#GenericApplicationContext()
AnnotationConfigApplicationContext#AnnotationConfigApplicationContext()
2.1 初始化AnnotatedBeanDefinitionReader (bd读取器)
AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader(BeanDefinitionRegistry)
初始化出一个注册器 (register也是spring环境,相等于AnnotationConfigApplicationContext)
AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry)
在给定的注册表中注册所有相关的属性
1)添加AnnotationAwareOrderComparator的对象,用于排序
2)添加ContextAnnotationAutowireCandidateResolver对象,用于处理延迟加载
3)往beanDefinitionMap中注册多个对象,包含(ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor等)
此处添加的一系列后置处理器,后面会使用到,PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors主要是
在spring的beanFactory初始化的过程中去做一些事情,怎么来做这些事情呢?委托了多个实现了BeanDefinitionRegistryPostProcessor
或者BeanFactoryProcessor接口的类来做这些事情,有自定义的也有spring内部的其中ConfigurationClassPostProcessor就是一个
spring内部的BeanDefinitionRegistryPostProcessor因为如果你不添加这里就没有办法委托ConfigurationClassPostProcessor做一些功能
标记 : A1
AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry,Object)
往beanDefinitionMap中注册一个对象
AnnotationConfigUtils#registerPostProcessor(BeanDefinitionRegistry, RootBeanDefinition, String)
2.2 初始化ClassPathBeanDefinitionScanner (bean扫描器) ???? 后面补充
ClassPathBeanDefinitionScanner#ClassPathBeanDefinitionScanner(BeanDefinitionRegistry)
2.3 注册bean或者注册一个配置类
此处是一个空壳方法,委托给AnnotatedBeanDefinitionReader注册
AnnotationConfigApplicationContext#register(Class... componentClasses)
实际执行注册的方法
AnnotatedBeanDefinitionReader#register(Class... componentClasses)
注册,此处就是解析bean,将bean数据放入BeanDefinition中
1)通过AnnotatedGenericBeanDefinition解析class
2)解析bean的作用域
3)根据规则生成bean name
4)处理类中常用的注解,并将注解信息放入BeanDefinition中
5)自定义注解解析
6)代理域的处理 springmvc中使用
AnnotatedBeanDefinitionReader#doRegisterBean
2.4 刷新
AbstractApplicationContext#refresh()
2.4.1 准备工作,设置启动时间,是否激活标识位,初始化属性源配置
AbstractApplicationContext#prepareRefresh
2.4.2 获取一个工厂
AbstractApplicationContext#obtainFreshBeanFactory
2.4.3 初始化工厂,准备工厂
AbstractApplicationContext#prepareBeanFactory
2.4.4 这里是个空方法, 允许在上下文子类中对bean工厂进行后处理。
AbstractApplicationContext#postProcessBeanFactory
2.4.5 这里就是执行BeanFactoryPostProcessors
AbstractApplicationContext#invokeBeanFactoryPostProcessors
2.4.5.1 依次执行BeanFactoryPostProcessors
1)会将AbstractApplicationContext中beanFactoryPostProcessors list中的数据遍历出来,
如果是BeanDefinitionRegistryPostProcessor类型,则执行它的postProcessBeanDefinitionRegistry方法
2)调用实现PriorityOrdered的BeanDefinitionRegistryPostProcessors获取到BeanName,根据BeanName去beanDefinitionMap中查找,最终生成对象
3)调用实现Ordered的BeanDefinitionRegistryPostProcessors。获取到BeanName,根据BeanName去beanDefinitionMap中查找,最终生成对象
4)调用所有其他BeanDefinitionRegistryPostProcessor(即不符合上述两种情况的),直到全部调用完成
2) 3) 4) 步骤中的数据即是标记 : A1中添加进beanDefinitionMap中的
5)执行所有BeanDefinitionRegistryPostProcessors后置处理器中的postProcessBeanFactory方法
6)执行所有常规BeanFactoryPostProcessors后置处理器中的postProcessBeanFactory方法
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory,java.util.List)
下面简单介绍下上面2)3)4) 中添加的BeanDefinitionRegistryPostProcessors
2.4.5.1.1 ConfigurationClassPostProcessor 这一块非常重要
1)从registry(factory)中获得所有BeanDefinitionNames
2)环境准备、 排序、 bean name生成策略
3)解析bean
ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
解析bean 这是一个空壳方法
ConfigurationClassParser#parse(java.util.Set)
ConfigurationClassParser#processConfigurationClass(ConfigurationClass)
1)递归处理内部类 一般很少用到
2)处理 @PropertySource注解,注入的属性
3) 处理@ComponentScan 属性
4)处理其他注解 包含 @Import @ImportResource @Bean 以及接口上的默认方法
ConfigurationClassParser#doProcessConfigurationClass(ConfigurationClass, SourceClass)
3)解析扫描包 最终委托给了componentScanParser去完成这件事
1. 创建一个扫描器
2. 从ComponentScan中获取nameGenerator(bean name生成策略)
3. 代理模型 web
4. 设置 resourcePattern
5. 设置includeFilters excludeFilters
6. 设置lazyInit 懒加载
7. 处理basePackages
8. 使用ClassPathBeanDefinitionScanner扫描包
ComponentScanAnnotationParser#parse(AnnotationAttributes, final String)
1) 将扫描到的bean ,存入BeanDefinition 然后放到set中
2) 遍历set,取出BeanDefinition,进一步处理,之后注册到factory中的BeanDefinitionMap中
ClassPathBeanDefinitionScanner#doScan(String... basePackages)
扫描包,并生成BeanDefinition
ClassPathScanningCandidateComponentProvider#findCandidateComponents
ClassPathScanningCandidateComponentProvider#scanCandidateComponents