快捷链接!
上一次已经看过了Reandr的代码,而Scaner则是使用ASM技术,emmmm ASM代码胎发咋 水平不够还是先不过多研究了
我们来看上一章没提到的那个三行构造方法
首先 this() 调用自己父类的 构造方法,
这就是他父类的构造方法,里面的代码很简单,就是创建了一个DefultListableBeanFactory。虽然这行代码简单,但是它创建了整个Spring中最重要的类之一 DefauleListableBeanFactory 为什么说他重要呢? 因为我们将经常使用这个类,而这个类是一个默认实现了的BeanFactory。而且这个BeanFactory基本是我们最常用到的BeanFactory了
我们转回头看AnnotationConfigApplicationContext中添加的构造方法
首先给Reander赋值,然后给Scanner赋值。
再声明Reader时,必定会执行他的构造函数。所以我们来看一下AnnotatedBeanDefinitionReader的构造函数。Reader的构造函数前面讲过,就不在重复了。
说过了this() 我们来看一下三行代码中的regist()
我们继续向内部,查看register()的代码
开始循环传入的class,然后挨个注册Bean 我们继续向内部
然后我们就会看到真正执行注册的这个函数 ,doRegisterBean()
代码很长 我们来一点一点的解析
首先我们来看第一行
第一眼我们应该先去看 new中传入的参数,是一个annotatedClass,一个类 那么理解这个函数,目的应为
为bean创建一个AnnotatedGenericBeanDefinition。AnnotatedGenericBeanDefinition,看起来名字很长,但其实很简单,这个类对象中存储着Bean的一些信息,例如是否懒加载,作用域等等。
然后紧跟着的是一个判断语句
这条判断语句,看名字我们可以明白,这个函数是判断是否需要跳过解析。其实说白了就是看这个类里面有没有注解,如果没有注解,那当然要跳过解析。
这里我多提一句,Spring再源码阅读的时候,要着重看一下函数和变量的名字,其实根据名字,它的功能就能猜的七七八八了。
根据刚才说的,看名字猜意思 这个函数应该是判断Bean的作用域。Emmmm看来是猜对了。
简简单单的一行代码,将 作用域加入Scope中。我们来看一下Scope的定义
这个scope被声明在AbstractBeanDefinition 中,这个类是AnnotatedBeanDefinition的一个父类
生成Bena的名字,然后给beanName赋值。众所周知再Spring中,如果不给bean起名字,Spring会给我们一个默认生成的名字。
这个函数的作用是处理类当中的通用注解,那么它都处理了什么? 我们去函数内部看一下。
可见它是处理Lazy DependsOn Primary Role等等注解的。
又是一个很长的If语句 嵌套for循环。 再Spring的使用中,如果使用一些额外的注解,比如@Qualifier @Primary之类的,它们会有特殊的作用,比如影响自动装配的选择,
上面这个if语句 就是来处理这个问题的。
是否配置了@Primary注解,如果加了则作为首选。
处理懒加载
如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一个根据名字自动装配的限定符
生成个BDHolder,这个BDHolder前面说过,这里不再赘述了。
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
这行代码与SpringMVC和Web有关系。
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
最后一行代码。
首先我们需要知道这么一个点,registy就是AnnotatonConfigApplicationContext。因为
AnnotationConfigApplicationContext实现了AnnotationConfigRegistry这个接口,是一个实现类。
而AnnotationConfigApplicationContext调用了自己父类的方法,它的父类中生成了一个BeanFactory,所以这个函数的主要作用是将BDHolder注册到那个BeanFactory中。