【读过的书,留下的迹】Spring技术内幕——深入解析Spring架构与设计原理

来源:互联网 发布:淘宝叶彬儿彩妆 编辑:程序博客网 时间:2024/04/30 06:13

前言

  最近发现有时候看完一本书,时间久了容易忘记,看书不总结思考效果大打折扣,故打算写这一系列文章,一是为了整理书中的要点,帮助自己消化理解;二是勉励自己多看书思考。文章中不会把书中内容讲解的非常详细,只是总结概括,适合已经阅读过该书的读者。

第2章:IoC容器的实现

  • spring有各式各样的IoC容器的实现,每一个均实现了BeanFactory这个基本的接口
  • spring通过定义BeanDefiniton来管理基于spring的应用中的各种对象以及它们的依赖关系

2.1 BeanFactory 和 ApplicationContext

  • BeanFactory实现是IoC容器的基本形式
  • ApplicationContext实现是IoC的高级形式
    • 支持不同信息来源
    • 自带访问资源ResourceLoader
    • 支持应用实践

2.2 IoC容器的初始化过程

  • 简单来说,IoC容器的初始化是由容器的构造函数中的refresh()方法来启动的,这个方法标志IoC容器正式启动,包括
    • BeanDefinition的Resource定位
    • BeanDefinition的载入
    • 以及注册(将Definition转为spring的数据结构存储,HashMap)

(1)BeanDefinition的Resource定位

Created with Raphaël 2.1.0xxxApplicationContextxxxApplicationContextAbstractRefreshableApplicationContextAbstractRefreshableApplicationContextFileSystemResourceFileSystemResourcerefreshBeanFactory()getResourceByPath()FileSystemResource

ps:箭头代表方法委托给某个类实现

  • 主要方法是protected Resource getResourceByPath(String path)

(2)BeanDefinition的载入和解析

IoC容器对Bean的管理和依赖注入功能,是通过对其持有的BeanDefinition进行各种相关操作

Created with Raphaël 2.1.0AbstractApplicationContextAbstractApplicationContextAbstractRefreshableApplicationContextAbstractRefreshableApplicationContextDefaultListableBeanFactoryDefaultListableBeanFactoryXmlBeanDefinitionReaderXmlBeanDefinitionReaderBeanDefinitionParserDelegateBeanDefinitionParserDelegaterefresh()createBeanFactory()loadBeanDefinition()parseBeanDefinitionElement()
  • 通过IoC容器的refresh启动整个BeanDefinition的载入,初始化通过XmlBeanDefinitionReader来实现
    • XmlBeanDefinitionReader
    • 委托BeanDefinitionParserDelegate
    • 调用doLoadBeanDefinitions读取
    • 调用registerBeanDefinitions开始载入
    • 创建createBeanDefinitionDocumentReader
    • 调用parseBeanDefinitonElement解析
    • 形成BeanDefinition

(3)BeanDefinition在IoC容器中注册

经过载入和解析后,BeanDefinition信息已经在IoC容器中,但还不能直接提供使用,需对BeanDefinition进行注册,通过HashMap持有载入的BeanDefinition,提供更友好的使用,BeanDefinition都在beanDefinitionMap里被检索和使用

Created with Raphaël 2.1.0XmlBeanDefinitionReaderXmlBeanDefinitionReaderDefaultBeanDefinitionDocumentReaderDefaultBeanDefinitionDocumentReaderDefaultListableBeanFactoryDefaultListableBeanFactoryprocessBeanDefinition()registerBeanDefintion()beanDefinitionMap

2.3 IoC容器的依赖注入

IoC容器接口中的getBean方法是触发依赖注入发生的地方

Created with Raphaël 2.1.0DefaultListableBeanFactoryDefaultListableBeanFactoryAbstractBeanFactoryAbstractBeanFactoryAbstractAutowireCapableBeanFactoryAbstractAutowireCapableBeanFactorySimpleInstantiationStrategySimpleInstantiationStrategyBeanDefinitionResolverBeanDefinitionResolverdoGetBean()createBean()instantiate()populateBean()applyPropertyValues()resolveReference()
  • 依赖注入关系特别密切的方法有createBeanInstance(创建)和populateBean(依赖的注入)
    • 创建Bean有两种方法:一种通过BeanUtils,使用JVM的反射功能;一种通过CGLIB,字节码生成器的类库,提供了一系列API来提供生成和转换Java的字节码的功能
    • populatedBean包括:首先处理autowire注入,属性注入,通过BeanDefinitionResolver对Bean Reference解析注入(其实Bean Reference的解析就是一个递归调用getBean获取其他依赖Bean的过程)

2.4 容器的其他相关特性

(1)ApplicationContext初始化与销毁

Created with Raphaël 2.1.0FileSystemXmlBeanFactoryFileSystemXmlBeanFactoryAbstractApplicationContextAbstractApplicationContextprepareBeanFactory()addPropertyEditorRegister()addBeanPostPrecessor()doClose()closeBeanFactory()

(2)Bean的作用域

作用域 描述 备注 singleton 在每个Spring IoC容器中一个bean定义对应一个对象实例 随着ApplicationContext一起实例化 prototype 一个bean定义对应多个对象实例 调用getBean时实例化 request 在一次HTTP请求中,一个bean定义对应一个实例;即每次HTTP请求将会有各自的bean实例, 它们依据某个bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext 情形下有效 只能用在基于web的Spring ApplicationContext session 在一个HTTP Session 中,一个bean定义对应一个实例。该作用域仅在基于web的SpringApplicationContext 情形下有效 只能用在基于web的Spring ApplicationContext global session 在一个全局的HTTP Session 中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于web的Spring ApplicationContext 情形下有效 只能用在基于web的Spring ApplicationContext

(3)Bean的生命周期

  • Bean实力创建
  • bean属性、依赖注入
  • 调用Bean的初始化方法
    • 调用一系列Aware接口,用来Bean对IoC容器的感知,如BeanNameAware、BeanFactoryAware、ApplicationContextAware
    • BeanPostProcessor,Bean后置处理器,用来监听事件发生,向容器注册后,具备接受IoC容器事件回调功能,两个接口
      • postProcessBeforeInitialization(),init-method前调用
      • postProcessAfterInitialization(),init-method后调用
    • 通过JDK的反射机制调用Bean的init-method进行初始化
  • 应用可以通过IoC容器使用Bean
  • 当容器关闭时,调用Bean的销毁方法
    • 若bean实现了DisposableBean接口,distroy()方法被调用
    • 如果指定了destroy-method=”close”定制的销毁方法,就调用这个方法

第3章:Spring AOP的实现

(1)流程

  • 利用反射技术以及第三方字节码技术,如CGLIB生成AopProxy代理对象
  • 根据配置中的Advisor配置拦截器
  • 将通知Advice适配成AdviceAdapter,以便调用

(2)概念

  • Advice通知
    • 定义在连接点做什么,为切面增强提供织入接口,如BeforeAdvice
  • Pointcut切点
    • 定义需要增强的方法集合,Pointcut接口中需返回一个MethodMatcher
  • Advisor通知器
    • 把Advice和Pointcut结合起来,完成Advisor

(3)原理

  • Spring AOP代理对象生成
    • Spring提供了两种方式来生成代理对象::JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理
  • AopProxy类中的invoke方法
    • 获取可以应用到此方法上的通知链(Interceptor Chain),如果有,则应用通知,并执行joinpoint;如果没有,则直接反射执行joinpoint。
  • invoke中的getInterceptorsAndDynamicInterceptionAdvice
    • 从提供的配置实例config中获取advisor列表,遍历处理这些advisor。如果是IntroductionAdvisor,则判断此Advisor能否应用到目标类targetClass上。如果是PointcutAdvisor,则判断,此Advisor能否应用到目标方法method上。将满足条件的Advisor通过AdvisorAdaptor转化成Interceptor列表(拦截器列表)返回。这一步Advisor被适配成AdvisorAdapter,即拦截器

第4章:Spring MVC与Web环境

(1)Web环境中的Spring MVC

  • 需要在web.xml中配置两个类
    • ContextLoaderListener:IoC容器的初始化
    • DispatchServlet:处理web请求的转发

(2)IoC容器的启动

Created with Raphaël 2.1.0ServletServletContextLoaderListenerContextLoaderListenerContextLoaderContextLoaderXmlWebApplicationContextXmlWebApplicationContextcontextInitialized()initWebApplication()loadParentContext()createWebApplication()refresh()WebApplicationContext

(3)DispatcherServlet处理过程

Created with Raphaël 2.1.0xxxxHttpServletBeanHttpServletBeanFrameworkServletFrameworkServletDispatcherServletDispatcherServletinitServletBean()initWebApplication()onRefresh()initStrategies()doGet()/doPost()processRequest()doService()doDispatch()

(4)doDispatch协同模型

Created with Raphaël 2.1.0DispatcherServletDispatcherServletHandlerMappingHandlerMappingHandlerInterceptorHandlerInterceptorHandlerAdapterHandlerAdapterViewResolverViewResolverViewViewcheckMultipart()getHandler()HandlerExecutionChainpreHandle()handle()ModelAndViewpostHandle()resolveViewName()getView()Viewrender()
0 0
原创粉丝点击