Spring四、Spring IOC、DI、MVC、AOP时序图

 最近一直在研究Spring IOC、DI、AOP、MVC几个步骤的源码,画出几种的时序图,方便以后查看回忆源码

1、IOC容器初始化

 IOC 容器的初始化包含了BeanDefinition资源文件Resource定位、解析加载和注册三个步骤。
 步骤依次为 : 读取资源文件为InputStream --> 转为Resource -> Document -> 解析元素节点封装为 BeanDefinition
-> 放入IOC容器中,即DefaultListableBeanFactory的 Map<String, BeanDefinition> beanDefinitionMap

  主要的几个类
  BeanFactory : BeanFactory及其子类也就是我们说的IOC容器,Spring提供了多种IOC容器以供选择
      ListableBeanFactory接口表示Bean可列表化、HierarchicalBeanFactory接口表示Bean有继承关系、AutowireCapableBeanFactory定义自动装配;
      以上三个接口的默认实现均为 org.springframework.beans.factory.support.DefaultListableBeanFactory
  BeanDefinition : 描述Bean在资源文件中的配置信息及相互关系
  BeanDefinitionReader : 解析资源为BeanDefinition 

1.1 基于xml的Ioc容器初始化

入口:

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class IoCTest {

    public static void main(String[] args) {
        //  
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        applicationContext.getBean("myUser");
        
    }
    
}

IOC实现流程及原理
Spring IOC时序图

1.2 基于web的Ioc容器初始化

入口: web Ioc容器初始化由DispatcherServlet.init()方法开始

  DispatcherServlet.init() 其实是调用的父类 org.springframework.web.servlet.HttpServletBean#init方法,之后 
    -> org.springframework.web.servlet.FrameworkServlet#initServletBean 
      -> org.springframework.web.servlet.FrameworkServlet#initWebApplicationContext
        -> org.springframework.web.servlet.FrameworkServlet#configureAndRefreshWebApplicationContext
          -> org.springframework.context.support.AbstractApplicationContext#refresh
            -> org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory
   到此,余下 web Ioc容器的初始化步骤和 XML IOC容器的初始化都经由 AbstractApplicationContext#obtainFreshBeanFactory 来完成,和上面时序图一样。

1.3 基于注解的Ioc容器初始化

component-scan 扫描指定包路径,解析class头的注解,及注解名称,封装为BeanDefinition;之后反射获取属性及value,封装为PropertyValue,赋值给BeanDefinition,最后放入Spring IOC容器中。

2、DI依赖注入时序图

  入口: org.springframework.context.support.ClassPathXmlApplicationContext#getBean(java.lang.String)  
        ->  org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.String)
  
  实现原理: 反射为属性赋值,如果存在循环依赖,使用三级缓存来处理:
      一级缓存: 类成功实例化,属性也成功赋值
      二级缓存: 类成功实例化,属性存在循环依赖、不能赋值 
      三级缓存: 类不能成功实例化 (指定使用构造器方法进行实例化,构造器中的参数存在循环引用) 
    在初始化完毕,会先遍历三级缓存进行依赖注入,放入一级缓存;然后遍历二级缓存,放入一级缓存; 

3、AOP时序图

  入口: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
  
  实现逻辑: 
    基于JDK或者Cglib的动态代理通过字节码重组实现;
    首先加载配置的切面PointCut及方法拦截通知Advice的配置,在进行依赖注入时,为每个类及类的每个方法正则匹配是否符合切面表达式,符合的话判断该类是否实现了接口,实现接口的话使用JDK的动态代理,否则使用Cglib的动态代理字节码重组重新织入通知代码,以次生产新的代理类。    

  AdvisedSupport -> AopConfig -> Advice -> JDKProxy or CglibProxy

4、MVC流程时序图

  入口: DispatcherServlet.init()  &&   DispatcherServlet.doService()

  实现逻辑:
  首先程序启动初始化Spring九大组件:
    初始化url映射HandlerMapping; 扫描Controller下的所有RequestMapping,组成正则类型的url Pattern,并与Controller、method绑定关系组成HandlerMapping对象;
    初始化参数适配器HandlerAdapter;记录RequestMapping对应method的参数类型,参数名称,RequestParam绑定名称等
    初始化视图解析器ViewResolver;
    .... 
  之后再页面url发出请求后,根据请求url正则匹配到对应1到多个HandlerMapping,然后找出对应的参数适配器HandlerAdapter,反射进行方法调用返回ModelAndView,再由ViewResolver进行解析、占位符替换,最后对View渲染,将html或jsp通过Response返回   

  DispatcherServlet -> HandlerMapping -> HandlerAdapter -> ModelAndView -> ViewResolver -> View  

posted @ 2020-02-29 21:34  BigShen  阅读(1552)  评论(0编辑  收藏  举报