Java框架-Spring系列

BeanFactory和ApplicationContext的区别

  • beanfactory是spring容器的访问根接口,是访问spring容器的基本调用方式。beanfactory持有着所有bean定义,容器中的bean可以是单例也可以是非单例。beanFactory同时也作为应用组件的注册器,可以集中配置应用组件
  • ApplicationContext是beanFactory的拓展接口,主要目标是为应用运行所需的配置bean,并添加一些增强功能
  • 通过MessageSource提供国际化支持;
  • 提供事件发布订阅处理能力
  • 通过ResourceLoader提供文件加载能力
  • 容器的嵌套能力

Spring容器bean生命周期

  • 参考:Spring中所有的扩展点

  • spring容器负责管理创建的bean的生命周期,它存在创建初始化阶段,同样也存在着不需要使用bean是的一系列析构并将bean从容器中移除操作;

  • bean定义注册:会执行:BeanFactoryPostProcessor接口的实现类,对bean定义修改

  • 实例化:

    • 拓展点:**AwareBeanPostProcessor#postProcessBeforeInstantiation

      • 方法如果返回实例对象时会短路bean的实例化、属性注入和初始化,直接跳到BeanFactoryPostProcessorafter方法
      • 方法如果返回null,则正常执行doCreateBean->createBeanInstance进行实例化
    • 实例化的方法:

      1. 构造器实例化:@Component等注解都是构造器创建,@Bean也是
      2. 静态工厂:不需要工厂Bean实例,比如@Configuration注解的class中使用注解的静态方法**
      3. 实例工厂:需要先创建工厂bean,然后使用工厂bean创建实例。相对于静态工厂,实例工厂更加灵活
      4. 实现FactoryBean接口本质上是一种特殊的实例工厂,与spring集成高度集成,支持延迟初始化、自动AOP代理
  • 属性注入:doCreateBean->populateBean

    1. 拓展点:InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation,boolean 判断是否需要属性注入
    2. 拓展点:InstantiationAwareBeanPostProcessor#postProcessProperties
      • 执行属性注入,比如@Autowired等复杂注入的的实现方式
  • 初始化:doCreateBean->initializeBean

    1. 回调Aware接口
    2. BeanPostProcessor#postProcessBeforeInitialization
    3. @PostConstruct:实际上也是通过BeanPostProcessor实现的,不过执行顺序靠后
    • InitializingBean#afterPropertiesSet
    • initMethod:@Bean(initMethod=xxx)、xml指定的initMethod
    • BeanPostProcessor#postProcessAfterInitialization
  • 使用

  • 销毁

    • @PreDestory
    • DisposableBean->destroy

spring的拓展点

流程图片:

ioc实现

  • spring中ioc具体实现是BeanFactory,BeanFactory是spring ioc容器的核心接口。
  • 主要两个核心的能力实现ioc
    • 1、容器+工厂:BeanFactory持有并管理者所有的bean定义、bean对象,掌握着bean生命周期
    • 2、BeanFactory提供一种bean的配置机制也就是依赖注入,让任何类型的对象都可以通过配置
  • 这种灵活的ioc机制也让spring容器更加容易和其他技术集成融合和拓展。比如ApplicationContext作为BeanFactory子接口,通过MessageSource拓展国际化能力,SpringAop的集成,事件传播能力

控制反转思想

  • ‘反转’本质是控制权归属的转移:从“开发者控制对象生命周期”反转为“容器控制对象生命周期”。

  • 为什么叫“反转”?——好莱坞原则解释

    “Don’t call us, we’ll call you.” (别找框架,框架会找你)

    • 正向调用:开发者作为调用方,主动调用框架API(如J2EE的EJBHome.create())。
    • 反转调用:容器作为调用方,主动执行开发者编写的组件(如调用@Service的方法)。

依赖注入对的实现

  • 主要依赖三种方式:构造器参数注入、set方法注入、反射注入

spring如何解决循环依赖

  • 通过三个Map解决,singletonFactories单例对象工厂的Map、earlySingletonObjects提前实例化的单例对象的Map、singletonObjects单例对象的Map
  • 假如A、B相互属性依赖
  • 在初始化A之前,先将A以工厂的形式加入到三级Map;使用工厂是因为如果A被AOP代理,那么B中的依赖A就应该是代理对象,需要提前为A生成代理。
  • 接着进行A的属性注入,此时发现需要一个B实例,这时候通过容器去获取B实例,发现三个Map都没有;
  • 接着会先去创建B实例,到这里还是正常的流程;
  • 在B的创建时,也会加入到三级Map,然后进行属性注入,这是发现需要A实例,并且在三级Map中发现有A,于是拿到A实例,并且把A移动到二级Map,B完成属性注入、初始化操作;
  • B创建完成,这时候在一级Map已经有B实例,这是后回到A的属性注入,A也顺利拿到B实例,属性注入完成;

二级缓存的作用

  • 处理循环依赖

  • **临时**存放需要提前暴露的bean,就是存在循环依赖的bean,提前暴露的bean是还没完成初始化的,只是new出来,尚未完成依赖注入。完成依赖注入、初始化后移动到一级缓存

三级缓存的作用

  • 处理循环依赖中的aop代理
  • **临时存放存在循环依赖并且需要aop代理的bean工厂对象。一个bean刚刚创建出来,会被包装成工厂对象**放到三级缓存,在存在循环依赖需要提前暴露这个bean时通过这个工厂对象获取到该bean的引用。
    • 工厂的作用:把判断是否需要创建代理和创建代理的过程包装起来,需要的时候在执行创建代理
      • 好处1:创建判断是否需要创建代理和创建代理的的逻辑可以复用
      • 好处2:对于有循环依赖的bean提前创建代理对象,对于没有循环依赖的bean延迟创建代理对象(延迟到postProcessAfterInitialization
    • 如果有aop,这个工厂对象会生成aop代理对象
    • 如果没有则返回bean引用
    • 如果没有没有循环依赖,三级缓存在初始化完bean后直接被删除
  • 三级缓存没有提高效率

说下springAop

  • Aop理解:aop是面向对象的延补充。开发中存在横向的系统级服务关注点、业务核心关注点。业务核心关注点一般数据和行为封装成各种业务对象,同时会包含着许多横向的系统级行为,如日志。统一的行为即可优化,通过面向切面的方式将这种统一的行为进行提取, 以提高系统的模块化,这就是aop所做的事情;
  • 通过通过AnnotationAwareAspectJAutoProxyCreator这个后置处理器在Bean生命周期的最后一步来完成AOP代理
  • springAop有两种实现方式:JDK动态代理、CGLIB代理
  • jdk代理实际上是一种接口代理,没有实现接口的对象则无法代理
  • CGLIB通过生成子类的方式进行代理,需要注意必须是非final类的对象,通过继承生成子类。
  • 目标(结果):分离应用的业务逻辑与系统级服务,提高应用的模块化。

spring事务实现方式

  • 1、通过编码式的事务;2、通过使用注解实现声明式事务
  • 事务传播行为
  • REQUIRED:默认行为。当前方法需要在事务中运行,如果已有事务则加入,没有则创建一个事务
  • SUPPORTS:当前方法运行的环境若有事务,则在事务中运行;若没有事务,则不再事务中运行
  • MANDATORY:当前方法必须运行在一个已有事务的环境中,否则报错
  • REQUIRES_NEW:当前方法会创建一个新的事务。若已有事务,则将事务挂起,方法运行结束在继续运行。
  • NOT_SUPPORTED:当前方法不需要事务。若已有事务,则将事务挂起直到该方法运行结束
  • NEVER:当前的方法不应该在一个事务中运行。如果一个事务正在进行,则会抛出一个异常。
  • NESTED:当前方法需要运行在一个事务中。若当前有事务,则创建一个子事务;若没事务,则创建一个新事务。子事务回滚不会导致父事务回滚

事务隔离级别

  • read uncommitted、read committed、repeatable read、serializable
  • 依赖于ioc、aop实现

Spring MVC 运行流程

  • 请求交给DispatchServlet,在这个Servlet中做统一的流程调度处理
  • 检查是否是文件上传请求,是的话预先处理文件
  • DispatchServlet中,通过request匹配找到HandlerMapping方法处理器,这个处理器只是一些元数据和拦截器处理链
  • 根据HandlerMapping找到HandlerAdapter,通过adapter执行接口逻辑,并获取执行结果
  • 将执行结果转换成响应的视图对象
  • 使用视图解析器解析视图对象并返回请求

Spring 框架中用到了哪些设计模式

  • 代理模式
  • 观察者模式
  • 策略模式 - 骑手结算中,根据不同条件采用不同的结算方法
  • 模板方法模式 - 发单流程里面,通过发单到不同配送平台,发单过程处理流程一样,只是数据流向不一样
  • 工厂模式
  • 单例模式: 唯一序列号生成器

springMVC原理

  • springMVC主要通过核心DispatchServlet执行调度处理请求,DispatchServlet将处理工作交给了几个核心组件完成:
  • 请求映射器HandlerMapping:根据url,head、请求方法、cookie等映射到相应的方法处理器;
  • 处理适配器HandlerAdapter:方法处理器的执行单位,请求映射器解析到请求的处理方法后仅有请求的元数据,需要通过设配器进行统一的适配执行;
  • 请求拦截器intercepter:请求拦截器,在执行方法处理器前后拦截执行,类似ServletAPI中的filter
  • 逻辑视图ModelAndView:方法处理器执行后返回的模型视图,包括返回的视图类型、请求执行结果、其他请求域数据
  • 视图解析器ViewResolver:HandlerAdapter执行完请求逻辑后返回一个逻辑视图,ViewResolver主要负责将逻辑视图解析成真实视图,可能是html视图、json视图等。

SpringSecurity的原理

  • ss是一个认证授权的框架,执行流程上主要是通过servletApi中的filter来实现认证授权。
  • ss有几个核心的组件,SecurityContextHolder,AuthenticationProvider,UserDetailsService
  • 在初始化的时候根据配置,生成uri与filter责任链的映射并存储在内存中
  • 当请求到达时,根据uri找到相应的filter处理链,然后执行相应的处理处理链;
  • 登录请求时,请求会进入到authticationfilter,通过调用AuthenticationProvider进行登录认证,认证通过后生成响应的认证上下文context,并在放到ThreadLocal中。