先以应用入手,再到理解原理,然后再理解源码。
以应用入手,比如说,@Controller注解、@Service注解。
二,BeanDefinition接口:不管是注解,还是xml配置文件,都是用来描述各种Bean的定义信息的一种方式。
在Spring源码里边,有一个十分重要且核心的接口,叫BeanDefinition。当然,这个接口里边会有一些具体的实现子类。
不管是xml也好,还是注解也好,定义好这些Bean的定义信息之后,最终都会转成一个BeanDefinition,将其交给Spring容器,然后Spring容器在识别到这些BeanDefinition之后,才能接着根据BeanDefinition里边的一些相关信息,来把我需要的Bean对象给创建出来。是这么一个过程。
如图所示:
三,Bean的定义信息,XML和注解,如何解析: 3.1,XML的配置文件如何解析:首先,通过IO流的方式,把这些配置文件给读取过来,读取过来之后,就是一堆的字符串。
字符串本身是没意义的,需要把这些字符串进行一个解析,如何解析呢,由于XML文件本身是自带格式的,所以说有一些现成的工具比如说document4j、SAS等等,这些工具就可以把这一堆的字符串来转成一系列的document对象。
然后下一步就可以将document对象转成一堆具有父子关系的Node节点,然后循环遍历Node节点,就可以取出这些Node节点里边的数据值。
当取到这些具体的数据值之后,就可以把这些具体的数据值来赋到我们具体的BeanDefinition对象中,然后就可以进行相应对象的创建了。
举例:
经过一系列的解析之后,就可以把这些具体的属性值,全部都赋值到具体的BeanDefinition对象中去,然后就可以去进行相应对象的创建了。
3.2,注解如何解析:注解形式也是一样的,首先是先获取到类上边的注解信息。
当获取到这些注解信息之后,就可以获取到具体的class信息。
有了具体的class信息,比如说name属性、value属性等等之后,就可以把这些具体的属性信息赋值到进行具体的BeanDefinition对象中,然后就可以进行相应对象的创建了。
3.3,总结,殊途同归:不管是XML还是注解,只是解析的方式不同而已,最终殊途同归,还是要将具有的数据值来赋值到BeanDefinition对象中,然后再去进行相应对象的创建。
四,对象具体创建的方式是什么? 当然是反射。当然是反射,几乎所有的框架创建对象的方式都是反射。
有人疑问:反射的效率不是很低吗?
其实实际情况是:
一,反射即使效率低,为什么还是要用反射呢,因为反射足够灵活!比如说当我获取到一个完全限定名(包名+类名)的时候,我们就可以根据这一个字符串来创建出我们需要的一个具体对象;
二,关于反射效率低这件事,当一下子创建十万个以上的对象的时候,反射才可能会出现效率低的问题,当实际上只是创建少量对象的时候,是不会出现任何的效率问题的。
所以说,关于怀疑反射是否效率低这件事,根本不需要去考虑这件事情。
五,Spring特点; 5.1,Spring具有非常好的扩展性;Spring的生态完整最根本的一个原因是,Spring具有非常好的扩展性,扩展性这一点也应该是学习Spring源码的时候最应该学习的知识。
因为在看源码的时候就会发现,源码里边很多地方都是可扩展的、留了很多的口子,让我们能够随意的对它进行扩展和优化。
六,正确认识BeanFactory: 6.1 ,正确理解BeanFactory;有人把BeanFactory翻译成Bean工厂,其实这是不准确的。
如图所示,其实在源码中,对于BeanFactory真正的描述是,BeanFactory它是一个用来访问Spring容器的一个根接口。
因为Spring它本身就是一个容器,容器里边可以存放很多的各种各样的Bean对象,而实际上BeanFactory更多的是用来访问Spring容器的一个入口。
如图所示:
为什么把BeanFactory称之为一个入口呢?
因为BeanFactory比较单一,它只提供了一些getBean()的方法,但是仅仅有getBean()方法在实际开发中可能不太够用,所以ApplicationContext对BeanFactory做了一些最基本的扩展功能,提供了一些更加完善的方法。
那怎么理解BeanFactory呢,你可以把它理解为是一个访问Spring容器的一个入口,也可以直接认为它就等同于容器对象,我们平时可以就把它的某一个实现子类就当作是我们整体的Spring容器。
比如说这个DefaultListableBeanFactory,这个类对象就是我们所创建的Spring容器,也就是说我们的所有的Bean对象都在这个DefaultListableBeanFactory类对象里边进行存放的。
而这个DefaultListableBeanFactory就是BeanFactory接口下边的一个实现子类。所以我们通常可以直接把BeanFactory就等同于Spring容器,当我们需要访问Sping容器的时候,可以直接通过BeanFactory来访问容器里边的一些Bean对象或者是属性值。
6.2,ApplicationContext与BeanFactory;首先,通过Idea中的show diagram查看一下ApplicationContext的继承关系:
所以,ApplicationContext,应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能;
1) 国际化(MessageSource)
2) 访问资源,如URL和文件(ResourceLoader)
3) 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层
4) 消息发送、响应机制(ApplicationEventPublisher)
5) AOP(拦截器)
而BeanFactory是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能;
七,PostProcessor,增强处理器: 7.1,BeanFactoryPostProcessor和BeanPostProcessor;BeanPostProcessor,有人把它称之为Bean的后置处理器,也有人把它称之为Bean的增强器,其实从功能上讲,称之为后处理器是不太准确的,应该叫做增强器更为合适。增强器是什么意思呢,它就是具体用来完成某些具体的扩展功能和实现的。
首先看这俩:
BeanFactoryPostProcessor和BeanPostProcessor有什么区别呢?
很明显,从类名就可以看出来,一个针对的是对BeanFactory对象进行的某些功能的增强,一个针对的是Bean对象进行的某些功能的增强。
7.2,BeanFactoryPostProcessor的postProcessBeanFactory()方法;在BeanFactoryPostProcessor的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法中,可以通过这里传进来的BeanFactory对象,来获取到BeanDefinition对象,继而对BeanDefinition对象去进行一些修改。
这个xml文件中的这个bean标签中的数据值最终会进入一个BeanDefinition对象里边。可以看到bean标签里边有一个property标签,property标签里边有一个value值,value值里边的占位符的实际值的最终替换环节,就是在BeanFactoryPostProcessor这个增强处理器里边进行完成的。
从最初的BeanDefinition保留原始值,到成为最终的BeanDefinition对象的过程中,可以有多个BeanFactoryPostProcessor的实现类来进行增强处理。
如图所示:
八,很重要的refresh()方法:org.springframework.context.support.AbstractApplicationContext # refresh()
这个refresh()方法很重要,里边包含了13个方法,如果想把Spring源码看明白,那么这13个方法是必须要搞懂的。如果这13个方法没搞懂,那说明Spring源码没看明白。
待更新...



