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 )(代码片段
Android 插件化VirtualApp 源码分析 ( 目前的 API 现状 | 安装应用源码分析 | 安装按钮执行的操作 | 返回到 HomeActivity 执行的操作 )(代码片段
Spring boot:thymeleaf 没有正确渲染片段
Android 事件分发事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )(代码片段