Spring面试题汇锦

什么是Spring?

Spring 是一个轻量级的 IoC 和AOP 容器框架。是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。
主要由以下7个模块组成:

  • Spring Core:核心类库,所有功能都依赖于该类库,提供IoC 和 DI 服务。
  • Spring Context :提供框架式的Bean访问模式,以及企业级功能(JNDI、定时任务等)。
  • Spring AOP :AOP 服务
  • Spring DAO:对JDBC的抽象封装,简化了数据访问异常的处理,并能统一管理JDBC事务。
  • Spring ORM: 对现有的ORM框架的支持。
  • Spring Web:提供了基本的面向Web的综合特性,提供对常见框架(如Struts2)的支持,Spring能管理这些框架,将Spring资源注入给这些框架,也能在这些框架的前后插入拦截器。
  • Sping MVC:提供面试Web应用的 Model-View-Controller(MVC) 实现。

Spring的优点

  • 低侵入式设计,对代码的污染极低。
  • Spring的 DI 机制将对象之间的依赖关系交由框架处理,降低了组件间的耦合性。
  • Spring 提供了AOP 技术,支持将一些通用任务,如安全、事务、日志、权限等继续集中式管理,从而提供更好的复用。
  • 对于主流的应用框架提供了集成支持。

对于Spring 的AOP理解

OOP(面向对象编程),允许开发者定义纵向的关系,但并不适用与定义横向的关系,会导致大量代码的重复,而不利于各个模块的应用。
AOP(面向切面编程),是作为面向对象的补充,用于将那些与业务无关却对多个对象产生影响的公共行为和逻辑,抽象并封装为一个可重用的模块,并将这个模块命名为“Aspect(切面)”。可减少系统中的重复代码,降低模块间的耦合度,提高系统的可维护性。可用于权限认证、日志、事务处理等。
AOP的实现关键在于代理模式,AOP代理主要分为静态代理与动态代理。静态代理的代表为AspectJ:动态代理则以Spring AOP为代表。

  • AspectJ:
    也称编译时增强,AOP框架会在编译阶段生成AOP代理类,并将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。
  • Spring AOP:
    使用的动态代理。即AOP框架在每次运行时不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个对象包含了目标对象的全部方法,并且特定的切点做了增强处理,并回调原对象的方法。

Spring AOP 中的动态代理主要有两种方式,JDK动态代理与CGLIB动态代理:

  • JDK动态代理只提供接口的动态代理,不支持类的处理。核心是 InvocationHandler 接口和Proxy类,InvocationHandler通过 invoke()方法反射来调用目标类种的代码,动态的将横切逻辑和业务编织在一起。然后Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。
  • 如果代理类没有实现 InvocationHandler 接口,那么Spring AOP 会选择使用CGLIB来动态代理目标类。
  • CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态处理,因此若某个类被标记为 final ,那么其是无法使用CGLIB做动态代理的。

静态代理与动态代理的区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理具有更好的性能,但其需要特定的编译来进行处理,Spring AOP 则不需要。
InvocationHandler 的 invoke(Objectproxy,Methodmethod,Object[] args):proxy是最终生成的代理实例;method 是被代理目标实例的某个具体方法;args 是被代理目标实例某个方法的具体入参, 在方法反射调用时使用。

对于Spring的IoC理解

  • IoC即控制反转,指创建对象的控制权转移给Spring框架进行管理,并由Spring根据配置文件去创建实例和管理各个实例之间的依赖关系。对象与对象间的松散耦合也利于功能的服用。DI 与控制反转是同一个概念的不同角度的描述,即应用程序在运行时依赖IoC容器来动态注入对象需要的外部依赖。(可直观认为对象的创建交由Spring来自动进行,使用Java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法)
  • 三种IoC注入方式:构造器注入、setter方法注入、注解注入

IoC让相互协作的组件保持松散的耦合,AOP则允许将遍布于各应用层的功能分离出来形成可重用的功能组件

Spring AOP里面的几个名词的概念

  • 连接点(Join point):指程序运行过程中所执行的方法。在Spring AOP中,一个连接点总代表一个方法的执行。
  • 切面(Aspect):被抽取出来的公共模块,可以用来会横切多个对象。Aspect切面可以看成 Pointcut切点 和 Advice通知 的结合,一个切面可以由多个切点和通知组成。
    在Spring AOP中,切面可以在类上使用 @AspectJ 注解来实现。
  • 切点(Pointcut):切点用于定义 要对哪些Join point进行拦截。
    切点分为execution方式和annotation方式。execution方式可以用路径表达式指定对哪些方法拦截,比如指定拦截add*、search*。annotation方式可以指定被哪些注解修饰的代码进行拦截。
  • 通知(Advice):指要在连接点(Join Point)上执行的动作,即增强的逻辑,比如权限校验和、日志记录等。通知有各种类型,包括Around、Before、After、After returning、After throwing。
  • 目标对象(Target):包含连接点的对象,也称作被通知(Advice)的对象。 由于Spring AOP是通过动态代理实现的,所以这个对象永远是一个代理对象。
  • 织入(Weaving):通过动态代理,在目标对象(Target)的方法(即连接点Join point)中执行增强逻辑(Advice)的过程。
  • 引入(Introduction):添加额外的方法或者字段到被通知的类。Spring允许引入新的接口(以及对应的实现)到任何被代理的对象。例如,你可以使用一个引入来使bean实现 IsModified 接口,以便简化缓存机制。

Spring通知(Advice)类型

  • 前置通知(Before Advice):在连接点(Join point)之前执行的通知。
  • 后置通知(After Advice):当连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
  • 环绕通知(Around Advice):包围一个连接点的通知,这是最强大的一种通知类型。 环绕通知可以在方法调用前后完成自定义的行为。它也可以选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。
  • 返回后通知(AfterReturning Advice):在连接点正常完成后执行的通知(如果连接点抛出异常,则不执行)
  • 抛出异常后通知(AfterThrowing advice):在方法抛出异常退出时执行的通知
在同一个 Aspect 种,不同 advice 执行顺序

1) 无异常发生的情况

  • around before advice
  • before advice
  • target method 执行
  • around after advice
  • after advice
  • afterReturning

2)有异常发生的情况

  • around before advice
  • before advice
  • target method 执行
  • around after advice
  • after advice
  • afterThrowing
  • java.lang.RuntimeException: 异常发生

Spring容器的启动流程

1)初始化Spring容器,注册内置的BeanPostProcessor的BeanDefinition到容器中:

  • 实例化BeanFactory【DefaultListableBeanFactory】工厂,用于生成Bean对象
  • 实例化BeanDefinitionReader注解配置读取器,用于对特定注解(如@Service、@Repository)的类进行读取转化成 BeanDefinition 对象,(BeanDefinition 是 Spring 中极其重要的一个概念,它存储了 bean 对象的所有特征信息,如是否单例,是否懒加载,factoryBeanName 等)
  • 实例化ClassPathBeanDefinitionScanner路径扫描器,用于对指定的包目录进行扫描查找 bean 对象

2)将配置类的BeanDefinition注册到容器中

3)调用refresh()方法刷新容器:

  • prepareRefresh()刷新前的预处理
  • obtainFreshBeanFactory():获取在容器初始化时创建的BeanFactory
  • prepareBeanFactory(beanFactory):BeanFactory的预处理工作,向容器中添加一些组件
  • postProcessBeanFactory(beanFactory):子类重写该方法,可以实现在BeanFactory创建并预处理完成以后做进一步的设置
  • invokeBeanFactoryPostProcessors(beanFactory):在BeanFactory标准初始化之后执行BeanFactoryPostProcessor的方法,即BeanFactory的后置处理器
  • registerBeanPostProcessors(beanFactory):向容器中注册Bean的后置处理器BeanPostProcessor,它的主要作用是干预Spring初始化bean的流程,从而完成代理、自动注入、循环依赖等功能
  • initMessageSource():初始化MessageSource组件,主要用于做国际化功能,消息绑定与消息解析
  • initApplicationEventMulticaster():初始化事件派发器,在注册监听器时会用到
  • onRefresh():留给子容器、子类重写这个方法,在容器刷新的时候可以自定义逻辑
  • egisterListeners():注册监听器:将容器中所有的ApplicationListener注册到事件派发器中,并派发之前步骤产生的事件
  • finishBeanFactoryInitialization(beanFactory):初始化所有剩下的单实例bean,核心方法是preInstantiateSingletons(),会调用getBean()方法创建对象
  • finishRefresh():发布BeanFactory容器刷新完成事件

BeanFactory 和 ApplicationContext 的区别

BeanFactory 和 ApplicationContext 是Spring的两大核心接口,都可以当作Spring的容器。(ApplicationContext是BeanFactory的子接口)。

BeanFactory:
  • Spring里最底层的接口,包含了各种Bean的定义,读取Bean配置文档,管理Bean加载、实例化,控制Bean的生命周期,维护Bean之间的依赖关系。
  • 采用延迟加载形式来注入Bean,只有当某个Bean被需要是( 调用getBean() ),才进行加载实例化。即可能存在一些Spring的配置问题,如某个Bean的某个属性未被注入,BeanFactory加载后,直至第一次调用getBean方法才会抛出异常。
ApplicationContext:
  • 作为BeanFactory的派生,除了提供BeanFactory的全部功能外,还提供了更加完整的框架功能:
    1)继承 MessageSource,因此支持国际化。
    2)统一的资源访问方式。
    3)提供在监听器中注册bean的事件。
    4)同时加载多个配置文件。
    5)载入多个(有继承关系)上下文,使得每一个上下文都专注于一个特定的层次,比如应用的web层。
  • 在容器启动时就一次性加载创建了所有的Bean。

ApplicationContext 相对于 BeanFactory来说是重量级的,占用了更多的内存空间,当应用程序配置了较多Bean时,启动较慢。
BeanFactory 通常以编程的方式被创建,ApplicationContext还能被声明式创建,如使用ContextLoader。
两者都支持 BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。

Spring Bean 的生命周期

ps:Servlet 的生命周期:实例化、初始 init、接受请求service、销毁destroy

一般有四个阶段:实例化 Instantiation —> 属性赋值 Populate —> 初始化 Initialization—> 销毁 Destruction
具体阶段如图:
在这里插入图片描述

1) 实例化bean:
  • 对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用 createBean进行实例化。
  • 对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中的信息,实例化所有的bean。
2)设置对象属性(依赖注入)
  • 实例化后的对象被封装在BeanWrapper对象中,紧接着,Spring根据BeanDefinition中的信息 以及 通过BeanWrapper提供的设置属性的接口完成属性设置与依赖注入。
3) 处理 Aware 接口

Spring会检测该对象是否实现了xxxAware接口,通过Aware类型的接口,可以让我们拿到Spring容器的一些资源:

  • 如果这个Bean实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,传入Bean的名字;
  • 如果这个Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
  • 如果这个Bean实现了BeanFactoryAware接口,会调用它实现的setBeanFactory()方法,传递的是Spring工厂自身。
  • 如果这个Bean实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文。
4)BeanPostProcessor前置处理

如果想对Bean进行一些自定义的前置处理,那么可以让Bean实现了BeanPostProcessor接口,那将会调用 postProcessBeforeInitialization(Object obj, String s) 方法。

5) InitializingBean

如果Bean实现了InitializingBean接口,执行afeterPropertiesSet()方法。

6) init-method

如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。

7) BeanPostProcessor后置处理

如果这个Bean实现了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法;由于这个方法是在Bean初始化结束时调用的,所以可以被应用于内存或缓存技术;

以上几个步骤完成后,Bean就已经被正确创建了,之后就可以使用这个Bean了。

8)DisposableBean

当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的 destroy() 方法;

9)destroy-method

最后,如果这个Bean的Spring配置中配置了 destroy-method 属性,会自动调用其配置的销毁方法。

Spring Bean 的作用域

  • singleton:默认作用域,单例bean,每个容器中只有一个bean的实例。
  • prototype:为每一个bean请求创建一个实例。
  • request:为每一个request请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
  • session:与request范围类似,同一个session会话共享一个实例,不同会话使用不同的实例。
  • global-session:全局作用域,所有会话共享一个实例。如果想要声明让所有会话共享的存储变量的话,那么这全局变量需要存储在global-session中。

Spring Bean 的线程安全

  • 对于prototype作用域的Bean,每次都创建一个新对象,也就是线程之间不存在Bean共享,因此不会有线程安全问题。
  • 对于singleton作用域的Bean,所有的线程都共享一个单例实例的Bean,因此是存在线程安全问题的。但是如果单例Bean是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Controller类、Service类和Dao等,这些Bean大多是无状态的,只关注于方法本身。对于有状态的bean(比如Model和View),就需要自行保证线程安全,最浅显的解决办法就是将有状态的bean的作用域由“singleton”改为“prototype”。
  • 也可以采用ThreadLocal解决线程安全问题,为每个线程提供一个独立的变量副本,不同线程只操作自己线程的副本变量。

Spring 基于 xml 注入Bean的几种方式

  • set() 注入
  • 构造器注入:通过Index设置参数的位置或通过type设置参数的类型
  • 静态工厂注入
  • 实例工厂

Spring的自动装配

在spring中,使用autowire来配置自动装载模式,对象无需自己查找或创建与其关联的其他对象,由容器负责把需要相互协作的对象引用赋予各个对象。

在Spring框架xml配置中共有5种自动装配:
  • no:默认的方式是不进行自动装配的,通过手工设置ref属性来进行装配bean。
  • byName:通过bean的名称进行自动装配,如果一个bean的 property 与另一bean 的name 相同,就进行自动装配。
  • byType:通过参数的数据类型进行自动装配。
  • constructor:利用构造函数进行装配,并且构造函数的参数通过byType进行装配。
  • autodetect:自动探测,如果有构造方法,通过 construct的方式自动装配,否则使用 byType的方式自动装配。
基于注解的自动装配模式

使用@Autowired、@Resource注解来自动装配指定的bean。
在使用@Autowired注解之前需要在Spring配置文件进行配置:<context:annotation-config />
在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性。在使用@Autowired时,首先在容器中查询对应类型的bean:

  • 如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;
  • 如果查询的结果不止一个,那么@Autowired会根据名称来查找;
  • 如果上述查找的结果为空,那么会抛出异常。解决方法是,使用required=false。

@Autowired可用于:构造函数、成员变量、Setter方法

@Autowired和@Resource之间的区别:

  • @Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。
  • @Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。

Spring 如何解决循环依赖问题

三种循环依赖情况

  • 1) 通过构造方法进行依赖注入指产生的循环依赖问题
  • 2)通过 setter()方法进行依赖注入且是在多例(原型)模式下产生的循环依赖问题。
  • 3)通过 setter() 方法进行依赖注入且是在单例模式下产生的循环依赖问题

Spring中,只有第(3)种方式的循环依赖问题被解决了,其他两种方式在遇到循环依赖问题时都会产生异常。这是因为:

  • 第一种构造方法注入的情况下,在new对象的时候就会堵塞住了,其实也就是”先有鸡还是先有蛋“的历史难题。
  • 第二种setter方法(多例)的情况下,每一次getBean()时,都会产生一个新的Bean,如此反复下去就会有无穷无尽的Bean产生了,最终就会导致OOM问题的出现。

Spring在单例模式下的setter方法依赖注入引起的循环依赖问题,主要是通过二级缓存和三级缓存来解决的,其中三级缓存是主要功臣。解决的核心原理就是:在对象实例化之后,依赖注入之前,Spring提前暴露的Bean实例的引用在第三级缓存中进行存储。

解决构造函数相互注入造成的循环依赖:可以使用@Lazy注解来解决。
对于类A和类B都是通过构造器注入的情况,可以在A或者B的构造函数的形参上加个@Lazy注解实现延迟加载。@Lazy实现原理是,当实例化对象时,如果发现参数或者属性有@Lazy注解修饰,那么就不直接创建所依赖的对象了,而是使用动态代理创建一个代理类。
比如,类A的创建:A a=new A(B),需要依赖对象B,发现构造函数的形参上有@Lazy注解,那么就不直接创建B了,而是使用动态代理创建了一个代理类B1,此时A跟B就不是相互依赖了,变成了A依赖一个代理类B1,B依赖A。但因为在注入依赖时,类A并没有完全的初始化完,实际上注入的是一个代理对象,只有当他首次被使用的时候才会被完全的初始化。

Spring 三大缓存

Spring中有三个缓存,用于存储单例的Bean实例,这三个缓存是彼此互斥的,不会针对同一个Bean的实例同时存储。
如果调用getBean,则需要从三个缓存中依次获取指定的Bean实例。 读取顺序依次是 一级缓存 —> 二级缓存 —> 三级缓存。

1、一级缓存::Map<String, Object> singletonObjects:

作用:

  • 用于存储单例模式下创建的 Bean 实例(已经创建完毕的)。
  • 该缓存是对外的,即提供给使用Spring框架的程序员使用

存储结构:

  • K:bean 的名称
  • V:bean 的实例对象(有代理对象则指的是代理对象,已经创建完毕)
2、二级缓存:Map<String, Object> earlySingletonObjects

作用:

  • 用于存储单例模式下创建的Bean实例(该Bean被提前暴露的引用,该Bean还在创建中)。
  • 该缓存是对内使用的,指的就是Spring框架内部逻辑使用该缓存。
  • 为了解决引用最终如何替换为代理对象的问题(如果有代理对象)
3、三级缓存:Map<String, ObjectFactory<?>> singletonFactories

作用:

  • 通过ObjectFactory对象来存储单例模式下提前暴露的Bean实例的引用(正在创建中)。
  • 该缓存是对内使用的,指的就是Spring框架内部逻辑使用该缓存。
  • 此缓存是解决循环依赖最大的功臣。

数据结构:

  • K:bean的名称
  • V:ObjectFactory,该对象持有提前暴露的bean的引用
4、为什第三级缓存要使用 ObjectFactory

如果仅仅是解决循环依赖问题,使用二级缓存就可以了,但是如果对象实现了AOP,那么注入到其他bean的时候,并不是最终的代理对象,而是原始的。这时就需要通过三级缓存的ObjectFactory才能提前产生最终的需要代理的对象。


Spring 框架中使用的设计模式

  • 工厂模式:BeanFactory 就是简单工厂模式的体系,用来创建对象的实例。
  • 单例模式:Bean 默认为单例模式。
  • 策略模式:例如Resource的实现类,针对不同的资源文件,实现了不同方式的资源获取策略。
  • 代理模式:Spring 的 AOP 功能用到了JDK 的动态代理和CGLIB字节码生成技术。
  • 适配器模式:Spring AOP的增强或通知(Advice)使用到了适配器模式,Spring MVC中也是用到了适配器模式适配Controller 。
  • 模板方法:用来解决代码重复的问题,如 RestTemplate,JmsTemplate,JpaTemplate .
  • 观察者模式:定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖与它对象都会得到通知被自动更新,如Spring 中 listener 的实现 ApplicationListener。
  • 桥接模式:可以根据客户的需求能够动态切换不同的数据源。比如我们的项目需要连接多个数据库,客户在每次访问中根据需要会去访问不同的数据库。

Spring 事务的实现方式和实现原理

Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。Spring只提供统一事务管理接口,具体实现都是由各数据库自己实现,数据库事务的提交和回滚是通过binlog或者undo log实现的。
Spring会在事务开始时,根据当前环境中设置的隔离级别,调整数据库隔离级别,由此保持一致。

1、Spring 事务的种类

Spring 支持编程式事务管理和声明式事务管理:

  • 编程式事务管理使用 TranscationTemplate.
  • 声明式事务管理建立在 AOP 之上,其本质是通过 AOP 功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前启动一个事务,在执行完目标方法之后根据执行情况提交或回滚事务。

声明式事务的最大优点是不需要咋业务逻辑代码中参杂事务管理的代码,只需要在配置文件中做相关的事务规则声明或通过 @Transcation 注解的方式,便可以将事务规则应用到业务逻辑中,减少对业务代码的污染。
不足的是最细力度只能作用到方法级别,无法做到编程式事务那种代码块级别。

2、Spring 事务传播的机制

spring事务的传播机制说的是,当多个事务同时存在的时候,spring如何处理这些事务的行为。事务传播机制实际上是使用简单的ThreadLocal实现的,所以,如果调用的方法是在新线程调用的,事务传播实际上是会失效的

  • PROPAGATION_REQUIRED:(默认传播行为)如果当前没有事务,就创建一个新事务;如果当前存在事务,就加入该事务。
  • PROPAGATION_REQUIRES_NEW:无论当前存不存在事务,都创建新事务进行执行。
  • PROPAGATION_SUPPORTS:如果当前存在事务,就加入该事务;如果当前不存在事务,就以非事务执行。
  • PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  • PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则按REQUIRED属性执行。
  • PROPAGATION_MANDATORY:如果当前存在事务,就加入该事务;如果当前不存在事务,就抛出异常。
  • PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
3、Spring 中的事务隔离级别
  • ISOLATION_DEFAULT:这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。
  • SOLATION_READ_UNCOMMITTED:读未提交,允许事务在执行过程中,读取其他事务未提交的数据。
  • ISOLATION_READ_COMMITTED:读已提交,允许事务在执行过程中,读取其他事务已经提交的数据。
  • ISOLATION_REPEATABLE_READ:可重复读,在同一个事务内,任意时刻的查询结果都是一致的。
  • ISOLATION_SERIALIZABLE:所有事务逐个依次执行。

Spring 框架中有哪些不同类型的事件

Spring 提供了一下5种标志的事件:

  • 上下文更新事件(ContextRefreshedEvent):在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
  • 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
  • 上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
  • 上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
  • 请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。

如果一个bean实现了ApplicationListener接口,当一个ApplicationEvent 被发布以后,bean会自动被通知。


本文大部分参考 : https://blog.csdn.net/a745233700/article/details/80959716 内容进行编写,小部分作了改动,如有错漏,烦请谅解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值