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方法==

  1. 调用 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源码总结:

  1. @EnableAspectJAutoProxy 开启AOP功能

  2. EnableAspectJAutoProxy 会给容器中注册一个AnnotationAwareAspectJAutoProxyCreator

  3. AnnotationAwareAspectJAutoProxyCreator 是一个后置处理器

  4. 容器的创建流程

    1. registerBeanPostProcessors() 注册后置处理器,创建AnnotationAwareAspectJAutoProxyCreator对象
    2. finishBeanFactoryInitialization() 初始化剩下的单实例bean
    3. 创建业务逻辑组件和切面组件
    4. AnnotationAwareAspectJAutoProxyCreator 拦截组件的创建过程
    5. 组件创建完成之后,判断组件是否需要增强
      1. 是,切面的通知方法,包装成增强器(Advisor);给业务逻辑组件创建一个代理对象(Cglib)。
  5. 执行目标方法:

    代理对象执行目标方法

    CglibAopProxy.intercept();
    得到目标方法的拦截器链,(增强器包装成拦截器MethodInterceptor)
    利用拦截器的链式机制,一次进入每一个拦截器进行执行

    1. 效果:

      ? 正常执行:前置通知——》目标方法——》后置通知——》返回通知

      ? 异常执行:前置通知——》目标方法——》后置通知——》异常通知

面试题:

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.请求结束,放回线程池,等待被调用;

(注意:避免使用实例变量(成员变量),因为如果存在成员变量,可能发生多线程同时访问该资源时,都来操作它,照成数据的不一致,因此产生线程安全问题)

相关推荐