1.spring简介
2.spring容器流程梳理
3.总结
1.spring简介
spring我置信大家都不生疏,只有你是一位JAVA开发人员,必定会应用它,然而咱们日常的应用中,很多时候只须要写业务逻辑,应用他人曾经封装好的技术,对其原理却无所不知。在此系列的博客中,笔者心愿尽可能地总结spring源码,让咱们不再只会应用它,让读者懂其原理。
所谓:有道无术,术尚可求,有术无道,止于术。
框架的应用可能就是‘术’,而框架的底层实现原理,就是‘道’。有了‘道’之后,‘术’是能够依据本人的须要造出来的。就像晓得了数学公式是如何推导的,天然不必记住公式,还能对公式进行魔改,甚至创造公式。然而如果只有‘术’,就像只晓得了公式的形态,并不知道其起源,略微变一下咱们就认不出来了。
无论是学什么货色,笔者认为,积攒‘道’是十分重要的,且不可急功近利,否则就是欲速则不达。
2.spring容器流程梳理
咱们在应用spring的时候,应用最多的就是AOP和IOC。
IOC:管制反转
理念:让他人为咱们服务!
假如我当初须要一个对象,个别状况下咱们都是须要本人new进去,然而有了IOC之后,咱们将一些对象的控制权给了spring容器,当咱们想要的时候,spring就会本人把对象送来!
看到这里咱们可能比拟迷糊,还是不晓得ioc的具体应用,咱们来举个例子好了:
假如咱们有一个UserServiceImpl,是IUserService的实现类,然而咱们每次应用的时候,都须要:
IUserService userService = new UserServiceImpl();
因为很多中央都要用到这个对象,所以咱们要写很多很多个new UserServiceImpl();
如果此时,IUserService更改了需要,须要把所有IUserService的实现类UserserviceImpl全副改成UserserviceImpl2(),那代码更改量是十分恐怖的。然而如果有了IOC,咱们就能够和实现类解耦了。次要更改IOC容器外面的实现类,当咱们用到这个接口的实现类的时候,让它给咱们送来就行了(只须要批改一个中央)。
AOP:面向切面编程
咱们都晓得,在咱们编码的时候,事务管制,权限管制等代码逻辑,会像一把刀一样,横在咱们业务逻辑两头,咱们将这部分代码称之为,横切业务逻辑代码。
那么将这部分代码对立独立进来,将横切逻辑也业务逻辑拆散,并进行对立治理,这就是AOP。
有了AOP和IOC的概念之后,接下来咱们来梳理一下,spring的总体执行流程:
一开始,咱们学习spring框架,都是从配置文件开始的,咱们在spring配置文件中写一个bean,而后咱们再从容器中读出来。
xml配置文件:
<bean id="a" class="slf.A"> </bean>
//将xml加载到容器中ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");//从容器中获取beanA a = (A) classPathXmlApplicationContext.getBean(A.class);
通过上述代码,咱们大抵能够剖析出,咱们应用spring的时候,大略是这样一个执行逻辑:
咱们大略能够总结出这个逻辑,然而spring外面却远远不止这么多操作,咱们先来对下面这张图进行一个裁减,退出一个概念BeanDefinition!
BeanDefinition:
它是配置bean元信息的一个接口,蕴含:
1)领有属性存储的性能,比方类信息,比方加载模式(懒加载等等)
2)领有资源获取的能力,也就是读取配置资源的能力
3)对Bean对象的形容能力
因为有的bean不是马上被实例化的(lazy-load),而后也可能有的bean蕴含了其它bean的信息,也可能有的bean的属性值须要读取别的文件(${jdbc.username}),所以咱们须要beanDefinition。
那么,bean信息除了从xml中来,还能够从注解,json,yml,json等中央来,而后咱们还能够对此图进行一个裁减。
其实IOC容器外面,并不仅仅只有反射,这么简略,因而咱们对IOC容器也进行一个裁减。
咱们先引入一个概念,beanFactoryPostProcessor:
BeanFactoryPostProcessor接口,能够对BeanDefinition元数据进行操作。比方配置文件中的${jdbc.username},咱们能够应用BeanFactoryPostProcessor将它的值从文件中读取并赋值。
可见BeanFactoryPostProcessor能够批改BeanDefinition外面的属性值。
而后就是初始化,
在spring中,容器将对象的初始化和实例化分成了两步操作:
别离是初始化和实例化:
如图所示:
初始化,顾名思义,就是咱们平时所说的,在堆内存开拓一块空间
实例化比较复杂,分成了很多步,流程图如所示,咱们将它并入下面那个大图,再进行解说:
填充属性:
具体能够参考populateBean办法,大略就是拆卸一些对象,比方对象A外面有对象B,就将B从容器中取出来并装进入,这个办法后续会具体进行解说。
执行aware接口办法:
Aware接口的性能就是,一个类只有实现这个类接口的相干子类,则能够拿到相应的货色。
那么具体能够拿到什么呢?咱们能够看一下这个类有哪些实现接口:
比如说 ApplicationContextAware,咱们实现了这个接口,就能够从获取ApplicationContext 这个对象:
public class AwareDemo implements ApplicationContextAware { private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; }}
BeanPostProcessor:Before:
接下来执行beanPostProcessor前置办法,实现了这个接口的bean,咱们要执行它的前置办法
public class BeanPostProcessorDemo implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return null; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return null; }}
init-method:
如果bean的文件配置中有init标签,咱们就要执行它对应的办法:
<bean id="a" class="slf.A" init-method="init"> <property name="b" ref="b"/> </bean>
BeanPostProcessor:After:
后置办法,能够参考下面。
3.总结
明天咱们总结了Bean容器的大体的执行流程,也只是粗略地概括了一下,大抵能够用一张图来进行概括:
另外值得一提的是,beanFactoryPostProcessor和beanPostProcessor是有区别的,区别如图所示: