Spring
阅读提示
Spring 面试常见追问链路:IOC -> AOP -> 事务 -> 循环依赖。
建议先记住每个主题的结论句,再补关键机制细节。
1、SpringBean的作用域
参考回答:
- singleton:这是Spring框架的默认作用域。Spring IoC容器只会创建该Bean的唯一实例。所有对该Bean的请求都将返回同一个实例。这个Bean是全局共享的,适用于无状态的Bean或者需要在多个组件之间共享数据的情况。
- prototype:每次对该作用域下的Bean的请求都会创建新的实例。获取Bean(即通过
applicationContext.getBean等方法获取)及装配Bean(即通过@Autowired注入)都是新的对象实例。没有共享状态,适用于有状态的Bean或者需要频繁创建新实例的情况。 - request:每次HTTP请求都会创建一个新的Bean实例。每个请求的Bean实例对于该请求是唯一的。这个作用域仅在基于Web的Spring ApplicationContext中有效。适用于处理HTTP请求的控制器或服务。
- session:在一个HTTP会话(Session)中,定义一个Bean实例。对于同一用户的所有请求,都将使用相同的Bean实例。这个作用域也仅在基于Web的Spring ApplicationContext中有效,适用于保存用户特定的数据或状态。
- global session:在整个应用程序的全局会话中创建一个新的Bean实例。这个作用域主要用于在Portlet环境中定义Bean,因为Portlet规范定义了全局会话的概念,而普通的Web应用(只包含Servlet)中并没有这个概念。在普通的Web应用中,global session作用域等同于session作用域。
2、SpringBean的生命周期
参考回答:
- 实例化:当Spring IoC容器接收到对某个Bean的请求时,IoC容器会先通过反射机制实例化该Bean。这个阶段完成了
BeanFactoryPostProcessor的操作(如果有的话)。 - 属性赋值:Spring IoC容器在创建Bean的过程中,会将Bean在XML文件中配置的属性值和
BeanDefinition中的属性值设置到Bean中。这个过程也称为依赖注入(DI),可以通过构造方法注入、Setter方法注入等方式完成。 - Bean后处理器(BeanPostProcessor)处理:在Bean的实例化和属性赋值之后,Spring会调用
BeanPostProcessor的postProcessBeforeInitialization方法,对Bean进行进一步的处理。这是一个可选的步骤,开发者可以通过实现BeanPostProcessor接口并覆盖相应的方法来定义自己的处理逻辑。 - 初始化:如果Bean在容器中配置了
init-method,那么这个方法将会被调用,完成Bean的初始化操作。此外,如果Bean实现了InitializingBean接口,那么Spring会调用其afterPropertiesSet方法进行初始化。这也是一个可选的步骤,但通常用于在Bean的所有属性设置完毕后执行一些初始化操作。 - 实例化后处理:在Bean完成初始化之后,Spring会再次调用
BeanPostProcessor的postProcessAfterInitialization方法,对Bean进行最后的处理。这也是一个可选的步骤,开发者可以在这里添加一些额外的逻辑,例如对Bean进行代理等。 - 使用:此时Bean已经准备就绪,可以被应用程序使用了。Spring容器会管理Bean的生命周期,并在需要的时候将其提供给应用程序。
- 销毁:当Spring容器关闭时,它会调用所有实现了
DisposableBean接口的Bean的destroy方法,并触发在XML配置文件中定义的destroy-method。这是Bean生命周期的最后阶段,用于释放Bean占用的资源。
3、Spring AOP原理
参考回答:
Spring AOP(Aspect Oriented Programming,面向切面编程)的原理主要基于动态代理模式,用于在不修改原有业务代码的前提下,为多个目标对象统一管理并增加额外功能。其核心概念包括切面(Aspect)、连接点(Join Point)、通知(Advice)等。
切面(Aspect):切面是织入到目标类中的功能代码,对于Java来说可以是方法、构造器或者类的特定点上的代码。切面可以包括前置通知、后置通知、环绕通知、异常通知和最终通知等,具体可以根据业务需求自定义实现。
连接点(Join Point):连接点表示切面将会被织入到目标对象的哪个位置,对于Java来说通常是某个方法的执行点或者某个构造器的创建点。
通知(Advice):通知包括各种类型的切面代码,如前置通知、后置通知、环绕通知、异常通知和最终通知等。这些通知会在连接点执行时被触发。
Spring AOP以动态代理技术为主要方式进行织入。具体来说,当目标对象的方法被调用时,Spring AOP会检查该方法是否是一个连接点。如果是,则会在方法执行前后(或者方法执行过程中)织入相应的通知代码。这些通知代码可以在不修改原有业务代码的情况下,为目标对象增加额外的功能。
4、Spring事务传播机制
参考回答:
REQUIRED(默认):
如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
SUPPORTS:
如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
MANDATORY:
如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
REQUIRES_NEW:
创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说,无论外部方法是否开启事务,
REQUIRES_NEW修饰的内部方法都会新开启自己的事务,且开启的事务相互独立,互不干扰。NOT_SUPPORTED:
以非事务方式运行,如果当前存在事务,则把当前事务挂起。
NEVER:
以非事务方式运行,如果当前存在事务,则抛出异常。
NESTED:
如果当前存在事务,则在嵌套事务内执行。嵌套事务是独立的事务,但它可以依赖于外部事务的提交或回滚。如果外部事务提交,则嵌套事务也会提交;如果外部事务回滚,则嵌套事务可以选择性地回滚(这取决于它自己的状态)。
5、什么是Spring的循环依赖问题?(了解)
参考回答:
- Spring的循环依赖问题是指在Spring容器中,两个或多个Bean之间相互依赖,形成了一个循环引用的情况。具体来说,当一个Bean A依赖于另一个Bean B,而Bean B又依赖于Bean A时,就可能出现循环依赖的问题。
6、什么是spring三级缓存以及如何解决循环依赖(重要)
参考回答:
一级缓存(singletonObjects):
也称为“单例池”,用于存储所有单例bean的实例对象。
当应用程序需要某个bean时,Spring首先会在一级缓存中查找,如果找到则直接返回该bean的实例。
二级缓存(earlySingletonObjects):
存放早期暴露出来的bean对象,即实例化以后但属性还未填充的bean对象。
二级缓存在解决循环依赖中只是整个三级缓存机制的一部分,单独依赖二级缓存无法完全解决循环依赖问题。当A bean依赖于B bean,而B bean又依赖于A bean时,Spring可以在创建A bean的过程中将其提前放入二级缓存,以供B bean在实例化后但未填充属性前引用。
三级缓存(singletonFactories):
也称为“单例工厂池”,用于存储用于创建单例bean的ObjectFactory。
在创建单例bean时,如果发现该bean依赖于其他的bean,则需要先创建该依赖的bean实例。此时,Spring会将用于创建该依赖的ObjectFactory保存到三级缓存中。当依赖的bean创建完成后,Spring会使用这个ObjectFactory来生成最终的bean实例,并将其放入一级缓存中。
通过三级缓存机制,Spring可以更加高效地管理bean的创建和引用过程,特别是在处理循环依赖和懒加载等场景时。此外,缓存机制还可以减少对数据库等持久层资源的访问次数,提高系统的资源利用率和稳定性。
详细内容请看:[Srping 一级、spring二级、三级缓存是如何解决循环依赖的](https://www.yuque.com/g/yuqueyonghu5xvoli/fcplgi/uumgdn4cnophk8ev/collaborator/join?token=LRmHchsDTWHi4LYK&source=doc_collaborator# 《Srping 一级、spring二级、三级缓存是如何解决循环依赖的》)
6、spring事务失效的原因?
参考回答:
- 事务注解添加在非public方法上:Spring事务管理是基于AOP(面向切面编程)实现的,而AOP对于JDK动态代理或CGLib动态代理只会代理public方法。因此,如果@Transaction注解添加在非public方法上,事务将不会生效。
- 类没有被Spring管理:Spring事务是由AOP机制实现的,AOP机制的本质就是动态代理。从Spring IOC容器获取bean时,Spring会为目标类创建代理,从而支持事务。如果类没有被Spring容器管理(例如,没有添加@Service、@Component等注解),则Spring无法为目标类创建代理,事务也会失效。
- 异常被捕获且未正确处理:默认情况下,Spring只有在方法抛出运行时异常或者错误时才会回滚事务。如果事务方法内部抛出了异常,但该异常被catch语句捕获且没有重新抛出,或者捕获的异常类型不是运行时异常,那么事务将不会回滚。
- 事务属性设置不当:如果在Spring的事务管理中,事务的传播特性(propagation)或回滚规则(rollbackFor)设置不当,也可能导致事务失效。例如,如果在一个支持当前事务的方法中调用了需要新事务的方法,并且后者方法抛出了异常,但异常并未被Spring识别为需要回滚事务的异常,那么后者的事务将不会回滚。
- 数据库配置问题:如果数据库配置不支持事务(例如,使用了不支持事务的数据库引擎),或者数据库本身就是不支持事务的,那么Spring事务也会失效。
- 调用同一个类中的方法:在Spring中,如果一个事务方法内部调用了同一个类中的另一个方法,而这个方法没有被Spring代理(即没有被标记为@Transactional),那么事务将不会生效。这是因为Spring是通过代理模式来管理事务的,只有在代理对象上调用方法时,事务才会生效。
- 事务嵌套使用不当:在一个已经开启了事务的方法中再次开启事务,对于Spring的PROPAGATION_REQUIRED模式(默认模式),它只会用原来的事务,这可能导致预期之外的行为。
7、spring bean是否为线程安全的?
参考回答:
- Spring容器本身并没有提供Bean的线程安全策略,所以可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体情况还是要结合Bean的作用域来讨论。对于prototype作用域的Bean,每次都创建一个新对象,也就是线程之间不存在Bean共享,因此不会有线程安全问题。对于singleton作用域的Bean,所有的线程都共享一个单例实例的Bean,因此是存在线程安全问题的。
8、spring中用到的设计模式?
参考回答:
工厂模式(Factory Pattern):
Spring使用工厂模式通过
BeanFactory、ApplicationContext等接口创建并管理对象实例。这种方式将对象的创建与使用解耦,使得程序更加灵活和可扩展。单例模式(Singleton Pattern):
Spring中的Bean默认都是单例的,即在整个Spring IoC容器中,每个Bean只会有一个实例。这通过Bean的scope属性进行控制,当scope为singleton时,即表示使用单例模式。
代理模式(Proxy Pattern):
在AOP(面向切面编程)和remoting中被广泛使用。Spring AOP的实现基于动态代理模式,可以在运行时动态地将代码切入到类的指定方法、指定位置上。
模板方法模式(Template Method Pattern):
解决代码重复问题。Spring中例如
JdbcTemplate就是模板方法模式的体现,它封装了数据访问的底层操作,定义了数据访问的骨架,使得开发者可以只关注自己的业务SQL。前端控制器模式(Front Controller Pattern):
Spring MVC中的
DispatcherServlet就是前端控制器模式的实现,它负责接收请求,并根据请求信息调用相应的处理器(Controller)进行处理。依赖注入模式(Dependency Injection Pattern):
贯穿于
BeanFactory和ApplicationContext接口的核心理念。通过依赖注入,Spring可以在运行时动态地将一个对象所需要的外部依赖注入到该对象中,从而降低了代码的耦合度。装饰器模式(Decorator Pattern):
在Spring中,
BeanWrapper是一个很好的装饰器模式的例子。它允许你在运行时动态地给一个对象添加一些额外的职责。委派模式(Delegation Pattern):
在Spring MVC中,
DispatcherServlet就是一个典型的委派模式的例子。它接收请求,但并不处理请求,而是将请求委派给相应的控制器进行处理。策略模式(Strategy Pattern):
在Spring中,
HandlerMapping接口的实现类就使用了策略模式。它定义了一个处理请求的接口,具体的处理策略由实现类来完成。适配器模式(Adapter Pattern):
在Spring MVC中,
HandlerAdapter接口的实现类就使用了适配器模式。它将不同的处理器(Controller)适配成统一的接口,使得DispatcherServlet可以统一调用。观察者模式(Observer Pattern):
在Spring的事件驱动模型中,使用了观察者模式。当某个事件发生时,会通知所有注册的观察者(Listener)进行处理。
能说一部分就行了
9、Spring IOC
参考回答:
Spring IoC(Inversion of Control,控制反转)是Spring框架的核心特性之一。它的基本思想是将对象的创建和管理过程从应用程序代码中抽离出来,由Spring容器负责创建和管理对象之间的依赖关系。通过这种方式,应用程序代码不再需要直接创建和管理对象,而是向Spring容器发出请求,由容器负责创建和返回所需的对象。
Spring IoC的主要优点包括:
降低耦合性:通过IoC容器来管理对象之间的依赖关系,使得系统更加模块化、可测试和易于扩展。
提高灵活性和可维护性:由于对象的创建和管理由Spring容器负责,因此可以更加灵活地配置和修改对象的行为。同时,由于代码不再包含对象的创建和管理逻辑,因此可以更加专注于业务逻辑的实现,提高代码的可维护性。
支持多种配置方式:Spring IoC支持多种配置方式,包括XML配置、注解配置和Java配置等。这些配置方式可以根据项目的实际需求进行灵活选择和使用。
在实现Spring IoC时,有三种主要的方式:
使用XML实现Spring IoC:通过编写XML配置文件来定义和配置Bean,将配置信息集中在一个XML文件中进行管理。
使用注解方式实现Spring IoC:通过在类和方法上添加注解来定义和配置Bean,使得配置更加简洁、直观,并且减少了对XML文件的依赖。
使用JavaConfig实现Spring IoC:通过编写Java配置类来定义和配置Bean,将配置信息集中在一个Java类中,提供了一种更加面向对象和类型安全的配置方式。
10、spring AOP在项目中的应用场景?
参考回答:
- 日志记录:在系统中记录日志是非常重要的,可以使用AOP来实现日志记录的功能。通过在方法执行前、执行后或异常抛出时记录日志,可以方便地跟踪系统的运行情况和问题排查。
- 事务管理:在数据库操作或其他需要事务管理的操作中,使用AOP可以将事务管理的逻辑与业务逻辑分离,使得事务的控制更加简单和集中。通过AOP,可以在方法开始前开启事务,在方法执行完毕后提交或回滚事务,以确保数据的一致性和完整性。
- 安全控制:在系统中包含某些需要安全控制的操作,如登录、修改密码、授权等,可以使用AOP来实现安全控制的功能。通过AOP,可以在方法调用前进行安全性检查,例如检查用户的权限或身份验证,以确保只有授权用户可以访问特定的方法或资源。
- 性能监控:在系统运行过程中,有时需要对某些方法的性能进行监控,以找到系统的瓶颈并进行优化。通过AOP,可以在方法调用前后记录方法的执行时间,以监控和优化系统的性能。
- 缓存控制:在系统中有些数据可以缓存起来以提高访问速度,可以使用AOP来实现缓存控制的功能。通过AOP,可以在方法执行前查询缓存中是否有数据,如果有则返回,否则执行方法并将方法返回值存入缓存中。
- 异常处理:使用AOP,可以集中处理方法中抛出的异常,例如将异常转换为统一的错误码或进行日志记录。这有助于更好地管理和监控异常,并降低异常对系统的影响。
- 参数校验和转换:使用AOP,可以在方法调用前对方法的参数进行校验和转换,以确保参数的有效性和符合业务要求。这有助于减少因参数问题导致的错误和异常,并提高系统的健壮性。
12、Spring中如何开启事务?
参考回答:
编程式事务:
编程式事务是通过编程的方式自己去实现事务,比如事务的开启、提交、回滚操作,需要开发人员自己调用commit()或者rollback()等方法来实现。
这种事务管理方式需要在逻辑代码中手动书写事务控制逻辑,因此是侵入性的。它的缺点是代码复用性差,每一个事务都需要自己编写事务逻辑,可能会造成代码冗余。然而,它的优点在于事务边界更容易控制,可以在业务的任意位置进行事务提交或者回滚操作。
声明式事务:
声明式事务则是通过配置或注解的方式,将事务管理逻辑与业务逻辑进行分离,由Spring框架来自动处理事务的开启、提交和回滚。
使用声明式事务时,通常会在业务层(service层)的方法上、类上或接口上使用
@Transactional注解。当方法执行前,Spring会自动开启事务;如果方法成功执行完毕,Spring会提交事务;如果方法执行过程中出现异常,Spring会回滚事务。除了使用
@Transactional注解外,还需要在主配置类(通常是应用的入口类)上使用@EnableTransactionManagement注解来启用Spring的事务管理功能。
13、Spring ioc在项目中的应用场景?(了解)
参考回答:
解耦与模块化:
在复杂的系统中,各个组件之间可能存在复杂的依赖关系。使用Spring IoC,可以将这些依赖关系交由Spring容器管理,使得组件之间的耦合度降低,提高了系统的模块化程度。
依赖注入:
Spring IoC支持依赖注入(Dependency Injection, DI),这意味着Spring容器会自动将所需的依赖项注入到对象的实例中。这使得开发者无需在代码中手动创建和管理依赖对象,从而简化了代码并提高了可读性。
配置集中管理:
Spring IoC允许开发者将配置信息(如数据库连接信息、第三方服务接口地址等)集中在一个或多个配置文件中(如XML文件、Java配置类或YAML文件)。这样,当配置信息需要变更时,只需修改配置文件而无需修改代码。
插件化开发:
在一些大型系统中,可能需要支持多种插件或扩展。通过使用Spring IoC,可以将这些插件或扩展作为独立的组件进行开发,并通过配置文件或注解将它们集成到系统中。这使得插件的添加、删除和替换变得更加容易。
测试支持:
在测试过程中,可能需要模拟或替换某些组件的依赖项。Spring IoC提供了方便的测试支持,允许开发者在测试环境中注入模拟对象或测试数据,从而验证系统的正确性。
动态代理:
Spring IoC结合AOP(Aspect-Oriented Programming,面向切面编程)可以实现动态代理。动态代理允许开发者在不修改原始代码的情况下,为类添加额外的功能(如日志记录、事务管理、性能监控等)。这使得系统的功能扩展变得更加灵活和方便。
容器化应用:
在云原生和微服务架构中,应用通常以容器的形式部署。Spring IoC作为Spring框架的核心特性之一,可以与容器化技术(如Docker、Kubernetes等)很好地结合使用。通过Spring IoC管理应用的依赖关系,可以确保应用在容器化环境中能够正常运行并与其他服务进行交互。
14、SpringBoot和Spring的区别是什么?(了解)
参考回答:
- 设计理念:Spring是一个全面的框架,它提供了许多功能,但同时也增加了项目的复杂度。相反,Spring Boot旨在简化Spring应用程序的初始搭建和开发过程,尽可能自动配置Spring应用程序。基于“约定优于配置”的原则,Spring Boot简化了项目的配置流程。
- 创建独立应用:Spring Boot可以创建独立的Spring应用程序。它集成了Tomcat、Jetty和Undertow等服务器,并且不需要部署它们。这意味着开发者可以直接打包他们的应用程序为一个可执行的JAR或WAR文件,从而简化了部署过程。
- 配置:在Spring中,我们需要进行大量的XML配置、JavaConfig和注解处理,以整合各种组件。而在Spring Boot中,它使用了特定的方式来进行配置,极大地简化了这些文件的配置过程。例如,Spring Boot引入了“starters”的概念,这些是预先配置好的Maven依赖项,可以简化Maven配置。
- 嵌入式容器:Spring Boot嵌入了一个Web服务器(如Tomcat、Jetty或Undertow),这使得应用程序可以作为一个独立的可执行JAR或WAR文件运行,而不需要单独的服务器或容器。
- 自动配置:Spring Boot的强大之处在于其自动配置功能。它通过检查项目的类路径、属性设置和其他条件,自动为你配置Spring应用程序。例如,如果你在类路径中添加了H2数据库,Spring Boot会自动为你配置一个内存数据库。
- 依赖管理:在Spring Boot中,你只需要引入相应的starter依赖,就可以快速地整合第三方库和框架。这种依赖管理方式使得项目结构更加清晰,减少了版本冲突的可能性。
15、springBean的初始化过程?
参考回答:
- Bean的定义:
- 在Spring配置中定义Bean的信息,包括类名、属性、作用域等。
- Bean的加载和解析:
- Spring容器启动时,加载并解析配置文件或注解,生成
BeanDefinition对象。
- 实例化Bean:
- 根据
BeanDefinition,通过反射创建Bean实例。如果是单例Bean,会被缓存起来。
- 依赖注入:
- 为Bean注入所需的依赖,方式包括构造器注入、setter方法注入和字段注入。
- 初始化前处理:
- 如果存在
BeanPostProcessor,调用其postProcessBeforeInitialization方法,对Bean进行初始化前的定制化处理。
- 调用初始化方法:
执行Bean的初始化方法,可能包括:
实现
InitializingBean接口的afterPropertiesSet方法。在配置中指定的
init-method方法。使用
@PostConstruct注解的方法。
- 初始化后处理:
- 如果存在
BeanPostProcessor,调用其postProcessAfterInitialization方法,对Bean进行初始化后的定制化处理,如AOP代理等。
- Bean的就绪和使用:
- 经过上述步骤,Bean已完全初始化,可以通过
getBean()方法获取并使用。
16、如何在Spring启动过程中做缓存预热?
参考回答:
- 监听应用启动事件:Spring框架提供了多种方式来监听应用启动事件,以便在应用启动后执行特定的逻辑。你可以使用
@EventListener注解或实现ApplicationListener接口来监听ApplicationReadyEvent事件。当这个事件被触发时,意味着Spring应用已经启动并准备好接受请求了。 - 使用CommandLineRunner或ApplicationRunner:如果你不想直接监听
ApplicationReadyEvent事件,你也可以使用CommandLineRunner或ApplicationRunner接口。这两个接口都定义了一个run方法,Spring Boot会在所有Spring Beans都初始化完成之后调用这个方法。 - 使用@PostConstruct注解:使用 @PostConstruct 注解标注一个方法,该方法将在 Bean 的构造函数执行完毕后立即被调用。在这个方法中执行缓存预热的逻辑。
17、spring中常用注解?
参考回答:
组件注解:
@Component:用于标识一个类为Spring的组件,可以被自动扫描并注册为Bean。@Controller:用于标识一个类为控制器层(Controller)组件,通常用于处理HTTP请求。@Service:用于标注业务逻辑层组件,即Service层。@Repository:用于标识一个类为数据访问层(DAO)组件,用于操作数据库。@RestController:结合@Controller和@ResponseBody,用于标识一个类为RESTful风格的控制器,用于返回JSON或XML数据。注入注解:
@Autowired:由Spring提供,用于自动注入依赖。它默认按类型匹配的方式在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入到标注的变量中。@Qualifier:与@Autowired配合使用,用于在存在多个相同类型的Bean时,指定要注入的Bean的名称或限定符。@Resource:与@Autowired类似,但除了按类型匹配外,还支持按名称匹配。@Value:用于注入配置文件中的值或表达式的结果,例如注入一个字符串或数字常量。Java配置类相关注解:
@Configuration:用于标识一个类为配置类,通常与@Bean一起使用,以替代传统的XML配置文件。@Bean:注解在方法上,声明当前方法的返回值为一个Bean,用于在配置类中定义Bean。切面(AOP)相关注解:
@Aspect:声明一个切面,用于定义通知(Advice)和切点(Pointcut)。@Before、@After、@AfterReturning、@AfterThrowing、@Around:这些注解用于定义通知,分别表示在方法执行前、后、返回后、抛出异常后和环绕方法执行通知。其他常用注解:
@RequestMapping:用于映射Web请求到特定的处理器方法。@PathVariable:用于从URI模板变量中解析值,并绑定到方法参数上。@RequestParam:用于从请求参数中解析值,并绑定到方法参数上。@RequestBody:用于将HTTP请求正文转换为Java对象。@ResponseBody:用于将Java对象转换为HTTP响应正文。
18、spring中注入方式?
参考回答:
- set()方法注入;
- 构造器注入:①通过index设置参数的位置;②通过type设置参数类型;
- 静态工厂注入;
- 实例工厂;
19、spring中单例Bean是线程安全的吗?
参考回答:
- 不是,因为所有线程共享一个单例Bean,存在资源的竞争所以是线程不安全的,实际上大部分时间Bean是无状态的,所以说在某种程度上来说Bean其实是安全的。如果是有状态,那就需要开发人员修改bean的作用域。singleton改为prototype。
20、SpringMVC的执行流程?
- 用户发送请求至前端控制器 DispatcherServlet。
- DispatcherServlet 收到请求调用 HandlerMapping 处理器映射器。
- 处理器映射器找到具体的处理器(可以根据 xml 配置、注解进行查找),生成处理器及处理器拦截器(如果有则生成)一并返回给 DispatcherServlet。
- DispatcherServlet 调用 HandlerAdapter 处理器适配器。
- HandlerAdapter 经过适配调用具体的处理器(Controller,也叫后端控制器)
- Controller 执行完成返回 ModelAndView。
- HandlerAdapter 将 controller 执行结果 ModelAndView 返回给 DispatcherServlet。
- DispatcherServlet 将 ModelAndView 传给 ViewReslover 视图解析器。
- ViewReslover 解析后返回具体 View。
- DispatcherServlet 根据 View 进行渲染视图(即将模型数据填充至视图中)。
- DispatcherServlet 响应用户。


21、解释一下DispatcherServlet的作用?(了解)
- DispatcherServlet是Spring MVC的前端控制器,它负责接收所有的HTTP请求,并根据请求的类型和内容,将请求分发到相应的Controller进行处理。同时,它也负责将Controller返回的结果传递给视图进行渲染。
22、Spring MVC的主要组件?(了解)
- Spring MVC的主要组件包括DispatcherServlet(前端控制器)
- HandlerMapping(处理器映射器)
- HandlerAdapter(处理器适配器)
- Controller(控制器)
- ModelAndView(模型和视图)
- ViewResolver(视图解析器)。
23、SpringMVC 的常用注解有哪些?
- @RequestMapping :用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径;
- @RequestBody :注解实现接收 HTTP 请求的 json 数据,将 json 转换为 Java对象;
- @ResponseBody :注解实现将 Controller 方法返回对象转化为 json 对象响应给客户
24、@Controller注解的作用?(了解)
在Spring MVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示。在Spring MVC 中提供了一个非常简便的定义Controller 的方法,你无需继承特定的类或实现特定的接口,只需使用@Controller 标记一个类是Controller ,然后使用@RequestMapping 和@RequestParam 等一些注解用以定义URL 请求和Controller 方法之间的映射,这样的Controller 就能被外界访问到。此外Controller 不会直接依赖于HttpServletRequest 和HttpServletResponse 等HttpServlet 对象,它们可以通过Controller 的方法参数灵活的获取到。
@Controller 用于标记在一个类上,使用它标记的类就是一个Spring MVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping 注解。@Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器。单单使用@Controller 标记在一个类上还不能真正意义上的说它就是Spring MVC 的一个控制器类,因为这个时候Spring 还不认识它。那么要如何做Spring 才能认识它呢?这个时候就需要我们把这个控制器类交给Spring 来管理。有两种方式:
在Spring MVC 的配置文件中定义MyController 的bean 对象。
在Spring MVC 的配置文件中告诉Spring 该到哪里去找标记为@Controller 的Controller 控制器。
25、Spring事务的实现方式和原理以及隔离级别?
在使用Spring框架时,可以有两种使用事务的方式,一种是编程式的,一种是申明式的, @Transactional注解就是申明式的。
首先,事务这个概念是数据库层面的,Spring只是基于数据库中的事务进行了扩展,以及提供了一些能让程序员更加方便操作事务的方式。
比如我们可以通过在某个方法上增加@Transactional注解,就可以开启事务,这个方法中所有的sql都会在一个事务中执行,统一成功或失败。
在一个方法上加了@Transactional注解后,Spring会基于这个类生成一个代理对象,会将这个代理对象作为bean,当在使用这个代理对象的方法时,如果这个方法上存在@Transactional注解,那么代理逻辑会先把事务的自动提交设置为false,然后再去执行原本的业务逻辑方法,如果执行业务逻辑方法没有出现异常,那么代理逻辑中就会将事务进行提交,如果执行业务逻辑方法出现了异常,那么则会将事务进行回滚。
当然,针对哪些异常回滚事务是可以配置的,可以利用@Transactional注解中的rollbackFor属性进行配置,默认情况下会对RuntimeException和Error进行回滚。
spring事务隔离级别:
ISOLATION_DEFAULT:这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。
ISOLATION_READ_UNCOMMITTED:读未提交,允许事务在执行过程中,读取其他事务未提交的数据。
ISOLATION_READ_COMMITTED:读已提交,允许事务在执行过程中,读取其他事务已经提交的数据。
ISOLATION_REPEATABLE_READ:可重复读,在同一个事务内,任意时刻的查询结果都是一致的。
ISOLATION_SERIALIZABLE:所有事务逐个依次执行。
