Spring源码解析
Spring源码解析
IOC
(Inversion of Control):控制反转
1. ioc是一个容器,帮我们管理所有组件
2. 依赖注入(DI):@Autowired:自动赋值
3. 某个组件要使用Spring提供的更多(IOC,AOP),==必须注册到容器中。==
IOC源码核心
1)、ClassPathXmlApplicationContext 构造器 调用 Refresh()方法
2)、 Refresh()方法:
1. 加上同步锁保证IOC容器只会被创建一次 2. 准备了一个Bean工厂,并解析XML文件,将所有的配置信息保存起来 3. 注册Bean工厂的后置处理器,初始化消息源,(支持国际化功能), 4. 初始化一些事件转换器,注册一些监听器 5. 初始化其他的 beans 在我们的子类中 留给子类重写用的 方法 **onRefresh();** 6. ==finishBeanFactoryInitialization(beanFactory); 初始化单实例的地方。==
3)、finishBeanFactoryInitialization(beanFactory) 方法
1. AbstractApplicationContext 类下面的 ;Bean工厂;创建bean 2. 调用 beanFactory.preInstantiateSingletons(); 初始化所有单实例bean的地方
4)、==preInstantiateSingletons();==
1. 拿到所有的要创建的bean的名称 2. 按顺序创建bean (for each循环) 3. 根据bean的id 获取到bean的定义信息 4. 判断创建非抽象的的,单实例的,非懒加载的 5. 创建bean的细节 (getBean方法)
5)、==getBean方法==
- 调用 doGetBean(name, null, null, false);
6)、==doGetBean==方法
1. 先从已经注册的所有单实例bean中找,看有没有那个bean ==第一次创建是没有的== 2. 判断拿到创建当前bean之前所依赖的,需要提前创建的bean depend-on属性 (如果有就循环创建) 3. 调用:getSingleton(创建单实例bean)
7)、==getSingleton==方法
1. 先从容器将这个 bean get出来(第一次创建没有) 2. bean 创建 (千呼万唤始出来) 创建完成后调用添加单实例 3. 添加创建的bean,addSingleton方法
8)、==addSingleton==方法
1. 用synchronized 加锁 将所有的对象添加进容器(singletonObjects) 2. 单实例容器其实就是一个ConcurrentHashMap(256)
==getBean总结:==
- 转换 BeanName
- 从缓存中加载实例
- 实例化 Bean
- 检测依赖
- 创建 Bean
- 添加到 IOC 容器中
AOP
AOP源码总结:
@EnableAspectJAutoProxy 开启AOP功能
EnableAspectJAutoProxy 会给容器中注册一个AnnotationAwareAspectJAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator 是一个后置处理器
容器的创建流程
- registerBeanPostProcessors() 注册后置处理器,创建AnnotationAwareAspectJAutoProxyCreator对象
- finishBeanFactoryInitialization() 初始化剩下的单实例bean
- 创建业务逻辑组件和切面组件
- AnnotationAwareAspectJAutoProxyCreator 拦截组件的创建过程
- 组件创建完成之后,判断组件是否需要增强
- 是,切面的通知方法,包装成增强器(Advisor);给业务逻辑组件创建一个代理对象(Cglib)。
执行目标方法:
代理对象执行目标方法
CglibAopProxy.intercept();
得到目标方法的拦截器链,(增强器包装成拦截器MethodInterceptor)
利用拦截器的链式机制,一次进入每一个拦截器进行执行效果:
? 正常执行:前置通知——》目标方法——》后置通知——》返回通知
? 异常执行:前置通知——》目标方法——》后置通知——》异常通知
面试题:
BeanFactory和ApplicationContext 的区别:
ApplicationContext 是 BeanFactory的子接口;
BeanFactory :bean工厂接口,负责创建bean实例;容器里面的保存的所有单例bean其实是一个map,也是Spring 最底层的接口
ApplicationContext:是容器接口;更多的负责容器功能的实现;(可以基于BeanFactory创建好的对象之上完成强大的容器) 容器可以从map中获取这些bean,并且 aop,DI,实在ApplicationContext接口下的这些类里面。
==BeanFactory :是Spring 最底层的接口; ApplicationContext:是留给我们程序员使用的IOC容器接口;ApplicationContext 是 BeanFactory 的子接口。==
==Spring里面最大模式是工厂模式。==
` 类似于使用说明书
BeanFactory:bean工厂;工厂模式。帮用户创建bean。
Spring Bean的作用域
- singleton:默认作用域,容器里拥有唯一的Bean实例
- prototype:针对每一个getBean请求,容器都会创建一个Bean实例
- request:每个HTTP请求一个
- session:每个session创建一个Bean
- globalSession:每个全局的HTTP Session 创建一个Bean实例
Spring Bean 的生命周期
Bean的完整生命周期从 spring 容器开始实例化 bean 开始,到销毁。可以从三点来理解
1、 bean自身的方法:包括构造方法、 set 方法、 init-method 指定的方法、 destroy-method 指定的方法
2、 Bean级生命周期接口方法:如 BeanNameAware 、 BeanFactoryAware 等这些接口方法由 bean类实现。
3、 容器级生命周期接口方法:有InstantiationAwareBeanPostProcessor 、 BeanPostProcessor 等。一般称为后置处理器。他们一般不由bean 本身实现,独立存在,注册到 spring 容器中。 Spring 通过接口反射预先知道,当 spring 容器创建任何 bean 时,这些后处理器都会发生作用。
==Spring的传播机制==
- 1.如果当前没有事务,就新建一个事务;如果已存在一个事务,就加入到这个事务中。
- 2.支持当前事务,如果当前没有事务,以非事务方式执行。
- 3.使用当前事务,如果当前没有事务,则抛出异常。
- 4.新建事务,如果当前存在事务,则把当前事务挂起。
- 5.以非事务方式执行,如果当前存在事务,则把当前事务挂起。
- 6.以非事务方式执行,如果当前存在事务,则抛出异常。
- 7.如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 1. 类似的操作。
Servlet如何处理多个请求访问?
- Servlet容器默认是采用单实例多线程的方式处理多个请求的:
1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在一个Servlet实例);
2.容器初始化Servlet主要就是读取配置文件(可以通过servlet.xml的设置线程池中线程数目,初始化线程池通过web.xml,初始 化每个参数值等等。
3.当请求到达时,Servlet容器通过调度线程(Dispatchaer Thread) 调度它管理下线程池中等待执行的线程(Worker Thread)给请求者;
4.线程执行Servlet的service方法;
5.请求结束,放回线程池,等待被调用;
(注意:避免使用实例变量(成员变量),因为如果存在成员变量,可能发生多线程同时访问该资源时,都来操作它,照成数据的不一致,因此产生线程安全问题)