使用最广泛的Web应用框架

Spring系列文章

模块

Spring☆☆ - 图1

IoC

AOP

  • 静态代理:实现类
  • 动态代理:
    • JDK:实现接口,java反射机制生成一个代理接口的匿名类,调用具体方法的时候调用invokeHandler
    • CGLib:ASM字节码编辑技术动态创建类,基于ClassLoad装载,修改字节码生成子类去处理

Spring☆☆ - 图2

Bean

  • 注解
  • 生命周期(扫描类invokeBeanFactoryPostProcessors、封装beanDefinition对象各种信息、放到map、遍历map、验证能否实例化/是否单例/是否factory bean/单例池ConcorrentHashMap/正在创建的容器)、得到class、推断构造方法[根据注入模型/默认]、得到构造方法、反射实例化对象、后置处理器合并beanDefinition、判断是否允许循环依赖、提前暴露bean工厂对象、填充属性自动注入、执行部分aware接口、继续执行部分aware接口生命周期回调方法、完成代理AOP、beanPostprocessor的前置方法、实例化为bean、放到单例池、销毁)
  • 作用域(单例singleton、多例prototype、Request、Session)

    循环依赖

  • 情况:属性注入可以破解、构造器不行(三级缓存没自己,因为二级之后去加载B了)

  • 三级缓存:去单例池拿、判断是不是正在被创建的、判断是否支持循环依赖、二级缓存放到三级缓存、干掉二级缓存gc、下次直接从三级拿
  • 缓存存放:一级-单例bean、二级-工厂产生bean、三级-半成品

    父子容器

    事务实现原理

  • 采用不同的连接器

  • 用AOP新建立了一个链接(共享链接)
  • ThreadLocal当前事务
  • 前提是关闭AutoCommit

    事务传播行为

  • REQUIRED:如果当前没有事务,则自己新建一个事务,如果当前存在事务,则加入这个事务

  • SUPPORTS:当前存在事务,则加入当前事务,如果当前没有事务,就以非事务方法执行
  • MANDATORY:当前存在事务,则加入当前事务,如果当前事务不存在,则抛出异常
  • REQUIRES_NEW:创建一个新事务,如果存在当前事务,则挂起该事务
  • NOT_SUPPORTED:始终以非事务方式执行,如果当前存在事务,则挂起当前事务
  • NEVER:不使用事务,如果当前事务存在,则抛出异常
  • NESTED:如果当前事务存在,则在嵌套事务中执行,否则REQUIRED的操作一样(开启一个事务)

    设计模式

  • 单例

  • 工厂
  • 适配器:根据不同商家适配
  • 责任链:继承process链路执行

    refresh() 方法中调用的每个方法

  1. this.prepareRefresh() 激活开启容器
  2. this.obtainFreshBeanFactory() 获取 bean 工厂
  3. this.prepareBeanFactory(beanFactory) 对获取到的 beanFactory 做预处理设置
  4. this.postProcessBeanFactory(beanFactory); beanFactory准备工作完成后进行的后置处理工作
  5. this.invokeBeanFactoryPostProcessors(beanFactory) 执行 beanFactory 后置处理器的方法
  6. this.registerBeanPostProcessors(beanFactory) 注册 bean 的后置处理器
  7. this.initMessageSource() 初始化 MessageSource 组件
  8. this.initApplicationEventMulticaster() 初始化事件派发器,多播器
  9. this.onRefresh() 用来初始化子容器中的bean,默认是空方法
  10. this.registerListeners() 注册监听器
  11. this.finishBeanFactoryInitialization(beanFactory) 初始化所有剩下的单实例 bean
  12. this.finishRefresh() 完成ben的创建初始化工作,完成 IOC 容器的创建

    使用

    AnnotationConfigApplicationContext
    ClassPathXmlApplicationContext
    getBean

    整体过程

    扫描(找到目录—>获取所有class—>对单例非懒加载类构造BeanDefination和beanDefinationMap)和beanPostProcessorList—>遍历map创建单例bean(创建(推断构造方法—>依赖注入—>用BeanPostProcessor实现aware接口,比如BeanNameAware—>用BeanPostProcessor实现前初始化—>InitializingBean—>用BeanPostProcessor实现AOP)—>存入SingletonObjects单例池)

    Bean的创建生命周期

    XXX.class—>无参构造方法(推断构造方法)—>普通对象—>依赖注入(autowired属性赋值)—>实现aware接口—>初始化前(@PostConstruct)—>初始化(implements —>初始化(implements ) InitializingBean)—>[初始化后(AOP)—>代理对象]—>Bean
    多个构造方法尝试找无参构造方法,有的话就调用,没有就会报错,只有一个构造方法就没事
    依赖注入时从IoC容器 Map
    先按照类型去找1个直接用,不管名字
    如果有多个(覆盖@Bean会覆盖@Component/不覆盖),再按照名称去找

    Bean的销毁生命周期

    AOP

    XXXProxy—>代理对象—>代理对象.target=普通对象—>调用方法test()—>执行@Before切面逻辑—>调用target.test()
    代理对象的属性是空的,调用方法就有属性值了
    CGLib底层继承(父子类)

    怎么知道是否要AOP切面?

    是一种特殊的bean(@Aspect/@Component)
    找出所有的切面Bean—>遍历切面Bean—>遍历每个切面bean方法—>表达式是否匹配—>匹配则需要AOP—>匹配的所有方法缓存起来map供执行的时候用

    事务

    @Transaction
    也是生成代理对象,代理类的方法里{1.检查是否有@Transaction标注 2.事务管理器dataSource(A)创建一个数据库连接conn 3.conn.autocommit=false 4. target.test() 用dataSource(B)执行sql1 sql2 5.conn.commit()/conn.rollback()}

不加@Configuration,会造成两个不同的dataSource(A!=B),导致事务失效,@Configuration代理对象(先看容器中有没有dataSource的bean,有直接返回)

懒加载的单例bean

加上@Lazy注解第一次get的时候创建,默认非懒加载的单例bean
@Scope(“prototype”) 原型bean每次get的时候创建(多例)

扫描路径

@ComponentScan(“路径”)

事务如何传播的?

事务失效是因为代理对象持有的普通对象方法调用的事务方法,代理类去调用才有用,自己注入自己即可
@Transaction(propagation = Propagation.NEVER)
NEVER:以非事务的方式运行,存在一个事务则抛异常

SpringMVC工作原理

SpringBoot工作原理