1.说说Spring 里用到了哪些设计模式?

单例模式:Spring 中的 Bean 默认状况下都是单例的。无需多说。

工厂模式:工厂模式次要是通过 BeanFactory 和 ApplicationContext 来生产 Bean 对象。

代理模式:最常见的 AOP 的实现形式就是通过代理来实现,Spring次要是应用 JDK 动静代理和 CGLIB 代理。

模板办法模式:次要是一些对数据库操作的类用到,比方 JdbcTemplate、JpaTemplate,因为查询数据库的建设连贯、执行查问、敞开连贯几个过程,十分实用于模板办法。

2.谈谈你对IOC 和 AOP 的了解?他们的实现原理是什么?

IOC 叫做管制反转,指的是通过Spring来治理对象的创立、配置和生命周期,这样相当于把控制权交给了Spring,不须要人工来治理对象之间简单的依赖关系,这样做的益处就是解耦。在Spring外面,次要提供了 BeanFactory 和 ApplicationContext 两种 IOC 容器,通过他们来实现对 Bean 的治理。

AOP 叫做面向切面编程,他是一个编程范式,目标就是进步代码的模块性。Srping AOP 基于动静代理的形式实现,如果是实现了接口的话就会应用 JDK 动静代理,反之则应用 CGLIB 代理,Spring中 AOP 的利用次要体现在 事务、日志、异样解决等方面,通过在代码的前后做一些加强解决,能够实现对业务逻辑的隔离,进步代码的模块化能力,同时也是解耦。Spring次要提供了 Aspect 切面、JoinPoint 连接点、PointCut 切入点、Advice 加强等实现形式。

3. JDK 动静代理和 CGLIB 代理有什么区别?

JDK 动静代理次要是针对类实现了某个接口,AOP 则会应用 JDK 动静代理。他基于反射的机制实现,生成一个实现同样接口的一个代理类,而后通过重写办法的形式,实现对代码的加强。

而如果某个类没有实现接口,AOP 则会应用 CGLIB 代理。他的底层原理是基于 asm 第三方框架,通过批改字节码生成成成一个子类,而后重写父类的办法,实现对代码的加强。

4. Spring AOP 和 AspectJ AOP 有什么区别?

Spring AOP 基于动静代理实现,属于运行时加强。

AspectJ 则属于编译时加强,次要有3种形式:

  1. 编译时织入:指的是加强的代码和源代码咱们都有,间接应用 AspectJ 编译器编译就行了,编译之后生成一个新的类,他也会作为一个失常的 Java 类装载到JVM。
  2. 编译后织入:指的是代码曾经被编译成 class 文件或者曾经打成 jar 包,这时候要加强的话,就是编译后织入,比方你依赖了第三方的类库,又想对他加强的话,就能够通过这种形式。

  1. 加载时织入:指的是在 JVM 加载类的时候进行织入。

总结下来的话,就是 Spring AOP 只能在运行时织入,不须要独自编译,性能相比 AspectJ 编译织入的形式慢,而 AspectJ 只反对编译前后和类加载时织入,性能更好,性能更加弱小。

5. FactoryBean 和 BeanFactory有什么区别?

BeanFactory 是 Bean 的工厂, ApplicationContext 的父类,IOC 容器的外围,负责生产和治理 Bean 对象。

FactoryBean 是 Bean,能够通过实现 FactoryBean 接口定制实例化 Bean 的逻辑,通过代理一个Bean对象,对办法前后做一些操作。

6.SpringBean的生命周期说说?

SpringBean 生命周期简略概括为4个阶段:

  1. 实例化,创立一个Bean对象
  2. 填充属性,为属性赋值
  3. 初始化

    • 如果实现了xxxAware接口,通过不同类型的Aware接口拿到Spring容器的资源
    • 如果实现了BeanPostProcessor接口,则会回调该接口的postProcessBeforeInitialzationpostProcessAfterInitialization办法
    • 如果配置了init-method办法,则会执行init-method配置的办法
  4. 销毁

    • 容器敞开后,如果Bean实现了DisposableBean接口,则会回调该接口的destroy办法
    • 如果配置了destroy-method办法,则会执行destroy-method配置的办法

7.Spring是怎么解决循环依赖的?

首先,Spring 解决循环依赖有两个前提条件:

  1. 不全是结构器形式的循环依赖
  2. 必须是单例

基于下面的问题,咱们晓得Bean的生命周期,实质上解决循环依赖的问题就是三级缓存,通过三级缓存提前拿到未初始化的对象。

第一级缓存:用来保留实例化、初始化都实现的对象

第二级缓存:用来保留实例化实现,然而未初始化实现的对象

第三级缓存:用来保留一个对象工厂,提供一个匿名外部类,用于创立二级缓存中的对象

假如一个简略的循环依赖场景,A、B相互依赖。

A对象的创立过程:

  1. 创建对象A,实例化的时候把A对象工厂放入三级缓存

  1. A注入属性时,发现依赖B,转而去实例化B
  2. 同样创建对象B,注入属性时发现依赖A,一次从一级到三级缓存查问A,从三级缓存通过对象工厂拿到A,把A放入二级缓存,同时删除三级缓存中的A,此时,B曾经实例化并且初始化实现,把B放入一级缓存。

  1. 接着持续创立A,顺利从一级缓存拿到实例化且初始化实现的B对象,A对象创立也实现,删除二级缓存中的A,同时把A放入一级缓存
  2. 最初,一级缓存中保留着实例化、初始化都实现的A、B对象

因而,因为把实例化和初始化的流程离开了,所以如果都是用结构器的话,就没法拆散这个操作,所以都是结构器的话就无奈解决循环依赖的问题了。

8. 为什么要三级缓存?二级不行吗?

不能够,次要是为了生成代理对象。

因为三级缓存中放的是生成具体对象的匿名外部类,他能够生成代理对象,也能够是一般的实例对象。

应用三级缓存次要是为了保障不论什么时候应用的都是一个对象。

假如只有二级缓存的状况,往二级缓存中放的显示一个一般的Bean对象,BeanPostProcessor去生成代理对象之后,笼罩掉二级缓存中的一般Bean对象,那么多线程环境下可能取到的对象就不统一了。

9.Spring事务流传机制有哪些?

  1. PROPAGATION_REQUIRED:如果以后没有事务,就创立一个新事务,如果以后存在事务,就退出该事务,这也是通常咱们的默认抉择。
  2. PROPAGATION_REQUIRES_NEW:创立新事务,无论以后存不存在事务,都创立新事务。
  3. PROPAGATION_NESTED:如果以后存在事务,则在嵌套事务内执行。如果以后没有事务,则按REQUIRED属性执行。
  4. PROPAGATION_NOT_SUPPORTED:以非事务形式执行操作,如果以后存在事务,就把以后事务挂起。
  5. PROPAGATION_NEVER:以非事务形式执行,如果以后存在事务,则抛出异样。
  6. PROPAGATION_MANDATORY:反对以后事务,如果以后存在事务,就退出该事务,如果以后不存在事务,就抛出异样。
  7. PROPAGATION_SUPPORTS:反对以后事务,如果以后存在事务,就退出该事务,如果以后不存在事务,就以非事务执行。‘

10.最初,说说Spring Boot 启动流程吧?

这个流程,网上一搜根本都是这张图了,我也不想再画一遍了。那其实次要的流程就几个步骤:

  1. 筹备环境,依据不同的环境创立不同的Environment
  2. 筹备、加载上下文,为不同的环境抉择不同的Spring Context,而后加载资源,配置Bean
  3. 初始化,这个阶段刷新Spring Context,启动利用
  4. 最初完结流程