Spring源码

Posted xp1234

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring源码相关的知识,希望对你有一定的参考价值。

准备spring环境:

 1 @org.junit.Test
 2     public void test01(){
 3         //把spring所有环境准备好
 4         // 1.准备好DefaultListableBeanFactory
 5         //   实例化一个bdReader和一个Scanner
 6         AnnotationConfigApplicationContext applicationContext =
 7                 new AnnotationConfigApplicationContext();
 8 
 9         //把一个class转成bd,最后put到map
10         applicationContext.register(AppConfig.class);
15 
16         //初始化spring的环境
17         applicationContext.refresh();
18 
19 
20     }

构造方法

进入AnnotationConfigApplicationContext类:

1.调用AnnotationConfigApplicationContext()构造方法的时候,会先调用父类构造器new出一个工厂DefaultListableBeanFactory。

1 //new一个工厂DefaultListableBeanFactory
2     public GenericApplicationContext() {
3         this.beanFactory = new DefaultListableBeanFactory();
4     }

 2.初始化一个bean的读取器AnnotatedBeanDefinitionReader和一个扫描器ClassPathBeanDefinitionScanner。

       reader可以读取被加了注解的类,scanner可以扫描所有加了注解的bean。

 1 public AnnotationConfigApplicationContext() {
 2         /**
 3          * 父类的构造方法
 4          * 创建一个读取注解的BeanDefinition读取器
 5          * 什么是bean定义?BeanDefinition
 6          */
 7         //reader能够读取被加了注解的类      this是一个注册器,用来将BeanDefinition转为工厂中的map
 8         this.reader = new AnnotatedBeanDefinitionReader(this);
 9         //可以用来扫描包或者类,继而转换成bd
10         //但是实际上我们扫描包工作不是scanner这个对象来完成的
11         //是spring自己new的一个ClassPathBeanDefinitionScanner
12         //这里的scanner仅仅是为了程序员能够在外部调用AnnotationConfigApplicationContext对象的scan方法
13         this.scanner = new ClassPathBeanDefinitionScanner(this);
14     }

 3.进入this.reader = new AnnotatedBeanDefinitionReader(this)方法,一直到: 

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

       3.1  该方法中首先调用了unwrapDefaultListableBeanFactory()方法,这样获取到工厂。当前的工厂是一个空的工厂,给工厂设置依赖比较器(应该是这样翻译的吧),设置处理延迟加载的功能。

       3.2  设置BeanDefinitionHolder(装的是beanName+BeanDefinition,基本没啥作用,只是为了传参方便,本来传beanName和BeanDefinition,现在传BeanDefinitionHolder就可以)。

       3.3  将ConfigurationClassPostProcessor这个spring中的内置的类转为一个RootBeanDefinition,然后注册器BeanDefinitionRegistry将这个类注册进工厂,将这个RootBeanDefinition转换成beanName+BeanDefinition的方式放入BeanDefinitionHolder。

该registerAnnotationConfigProcessors方法的目的就是将ConfigurationClassPostProcessor类以及其他内置类装入BeanDefinitionHolder,然后返回BeanDefinitionHolder。

接下来回到2。然后是研究this.scanner = new ClassPathBeanDefinitionScanner(this);这里先放一下。

这样,AnnotationConfigApplicationContext()构造完成。

注册

接下来就是注册。进入applicationContext.register(AppConfig.class)方法。

4.进入doRegisterBean()方法:

 1 <T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
 2             @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
 3 
 4         /**
 5          * 根据指定的bean创建一个AnnotatedGenericBeanDefinition
 6          * 这个AnnotatedGenericBeanDefinition可以理解为一个数据结构
 7          * AnnotatedGenericBeanDefinition包含了类的其他信息,比如一些元信息
 8          * scope,lazy等等
 9          */
10         AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
11 
12         /**
13          * 判断这个类是否需要跳过解析
14          * 通过代码可以知道spring判断是否跳过解析,主要判断类有没有加注解
15          */
16         if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
17             return;
18         }
19 
20         //不知道
21         abd.setInstanceSupplier(instanceSupplier);
22         /**
23          * 得到类的作用域
24          */
25         ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
26         /**
27          * 把类的作用域添加到数据结构结构中
28          */
29         abd.setScope(scopeMetadata.getScopeName());
30         /**
31          * 生成类的名字通过beanNameGenerator
32          */
33         String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
34 
35         /**
36          * 处理类当中的通用注解
37          * 分析源码可以知道他主要处理
38          * Lazy DependsOn Primary Role等等注解
39          * 处理完成之后processCommonDefinitionAnnotations中依然是把他添加到数据结构当中
40          *
41          */
42         AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
43         //这里qualifiers传过来是null
44         /**
45          * 如果在向容器注册注解Bean定义时,使用了额外的限定符注解则解析
46          * 关于Qualifier和Primary前面的课当中讲过,主要涉及到spring的自动装配
47          * 这里需要注意的
48          * byName和qualifiers这个变量是Annotation类型的数组,里面存不仅仅是Qualifier注解
49          * 理论上里面里面存的是一切注解,所以可以看到下面的代码spring去循环了这个数组
50          * 然后依次判断了注解当中是否包含了Primary,是否包含了Lazyd
51          */
52         if (qualifiers != null) {
53             for (Class<? extends Annotation> qualifier : qualifiers) {
54                 ////如果配置了@Primary注解,如果加了则作为首选
55                 if (Primary.class == qualifier) {
56                     abd.setPrimary(true);
57                 }
58                 //懒加载,前面加过
59                 else if (Lazy.class == qualifier) {
60                     abd.setLazyInit(true);
61                 }
62                 else {
63                     //如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一个根据名字自动装配的限定符
64                     //这里难以理解,后面会详细介绍
65                     abd.addQualifier(new AutowireCandidateQualifier(qualifier));
66                 }
67             }
68         }
69         for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
70             customizer.customize(abd);
71         }
72 
73         /**
74          * 这个BeanDefinitionHolder也是一个数据结构
75          */
76         BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
77         /**
78          * ScopedProxyMode需要结合web去理解
79          * 

81 */ 82 definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); 83 84 /** 85 * 把上述的这个数据结构注册给registry 86 * registy就是AnnotatonConfigApplicationContext 87 * AnnotatonConfigApplicationContext在初始化的時候通過調用父類的構造方法 88 * 實例化了一个DefaultListableBeanFactory 89 * *registerBeanDefinition里面就是把definitionHolder这个数据结构包含的信息注册到 90 * DefaultListableBeanFactory这个工厂 91 */ 92 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); 93 }

(1)先把要注册的bean转为AnnotatedGenericBeanDefinition(AGBD),AnnotatedGenericBeanDefinition包括了bean的其他信息,比如一些元信息,scope,lazy等。

(2)把类的作用域的名字添加到AGBD中,并且得到注册bean的名字。processCommonDefinitionAnnotations()方法将AGBD中的信息拿出来进行处理,主要处理一些常用的注解,处理完成放回AGBD。

(3)把AnnotatedGenericBeanDefinition装入BeanDefinitionHolder,然后BeanDefinitionRegistry把BeanDefinitionHolder中的信息(bean)注册进入工厂。

 初始化Spring环境

5.进入refresh()方法。

(1)调用prepareRefresh()方法,这是刷新前的准备工作。获取容器的当时时间,同时给容器设置同步标识。

(2)refresh()-->obtainFreshBeanFactory()-->refreshBeanFactory()获取工厂

(3)调用prepareBeanFactory(beanFactory):给工厂设置ClassLoader,bean表达式解释器,添加后置管理器beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))

(4)postProcessBeanFactory(beanFactory)为容器的某些子类指定特殊的 BeanPost 事件处理器。

(5)invokeBeanFactoryPostProcessors(beanFactory),实例化并调用所有已注册BeanFactoryPostProcessor的bean,
必须在单例bean实例化之前调用。

    ----->invokeBeanFactoryPostProcessors()

以上是关于Spring源码的主要内容,如果未能解决你的问题,请参考以下文章

Android 逆向类加载器 ClassLoader ( 类加载器源码简介 | BaseDexClassLoader | DexClassLoader | PathClassLoader )(代码片段

如何进行 Java 代码阅读分析?

C# 获得目录创建时间的源码片段

Android 插件化VirtualApp 源码分析 ( 目前的 API 现状 | 安装应用源码分析 | 安装按钮执行的操作 | 返回到 HomeActivity 执行的操作 )(代码片段

Spring boot:thymeleaf 没有正确渲染片段

Android 事件分发事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )(代码片段