常见JAVA面试题总结<2020 java面试必备>(六)Spring/SpringMVC

说一下SpringMVC的核心架构

1)、tomcat 的工作线程将请求转交给spring mvc框架的 DispatcherServlet
2)、DispatcherServlet查找标注了@Controller注解的类,此时根据请求的uri,去定位到哪个Controller类来进行处理
3)、根据@RequestMapping去查找,使用这个Controller类的哪个方法来进行请求的处理
4)、在Controller的方法处理完后会有一个返回值,以前的时候,一般来说还是走jsp、模板技术,向DispatcherServlet 返回一个ModelAndView对象;然后会有一个 ViewResolver 结合Model和View,来渲染视图。
5)、现在前后端分离,Controller的方法处理完直接返回一个json串给前端

@ RequestMapping 的作用是什么

RequestMapping 是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径
RequestMapping 注解有六个属性,总共分成三类进行说明​

value, method

value:指定请求的实际地址,指定的地址可以是URI Template 模式(后面将会说明); method:指定请求的method类型, GET、POST、PUT、DELETE等;

consumes,produces

consumes:指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
​produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;

params,headers

params: 指定request中必须包含某些参数值是,才让该方法处理。
headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。

谈谈你对IOC的理解

IOC(Inverse of Control:控制反转)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring容器来管理,也就是说在Spring容器初始化时,根据你的xml配置,或者是注解,去实例化bean对象,底层的核心用的就是反射技术,通过反射直接根据你的类去自己构建对应的对象出来
Spring IOC 解决了系统类与类之间彻底的解耦合,假设有个 MyService 接口,有个 MyServiceImpl 实现类,如果没有IOC技术,则系统需要使用的地方都要通过 MyService myService = new MyServiceImpl() 方式来创建,如果现在有个新的实现类 NewServiceManagerImpl,这时但凡以前创建的地方全都要去改,改动代码成本很大,改动完以后的测试的成本很大

谈谈你对AOP的理解

AOP(Aspect-Oriented Programming:面向切面编程) 能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性
Spring AOP就是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用Cglib ,生成一个被代理对象的子类来作为代理​

Spring如何管理Bean的

工厂模式,Spring IOC 核心的设计模式的思想提现,他自己就是一个大的工厂,Spring容器初始化时,根据你的配置运用反射技术去实例化bean对象,把所有的bean实例都给放在了Spring容器里
如果你要使用bean,就找Spring容器就可以了,你自己不用创建对象了,后续如果有哪个接口的实现类发生改变了,只需要在创建Bean的地方去重新new新的实现类即可,这就是工厂模式的体现

Spring支持几种 bean 的作用域

(1)singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例
(2)prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例
(3)request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例。
(4)session:对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例。
(5)globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例

如果不指定Bean的作用域,Spring默认使用singleton作用域。一般来说在开发的时99.99%的时候都是用singleton单例作用域,因为 prototype 作用域Java在创建Bean实例时,需要进行内存申请;销毁实例时,需要完成垃圾回收,这些工作都会导致系统开销的增加
而 singleton 作用域的Bean实例一旦创建成功,可以重复使用。 因此,除非必要,否则尽量避免将Bean被设置成prototype作用域​

Spring中的Bean是线程安全的吗

Spring Bean默认来说,singleton,都是线程不安全的,在web系统,一般来说很少在Spring Bean里放一些实例变量,一般来说他们都是多个组件互相调用,最终去访问数据库的,所以即使有多个线程并发去访问,也不会造成什么影响

Spring中使用了哪些设计模式

工厂模式

Spring IOC 核心的设计模式的思想提现,他自己就是一个大的工厂,Spring容器初始化时,根据你的配置运用反射技术去实例化bean对象,把所有的bean实例都给放在了Spring容器里
如果你要使用bean,就找Spring容器就可以了,你自己不用创建对象了,后续如果有哪个接口的实现类发生改变了,只需要在创建Bean的地方去重新new新的实现类即可,这就是工厂模式的体现

单例模式

Spring默认来说,对每个bean走的都是一个单例模式,确保说你的一个类在系统运行期间只有一个实例对象,只有一个bean,用到了一个单例模式的思想,保证了每个bean都是单例的

代理模式

Spring AOP 核心的设计模式的思想提现,如果说你要对一些类的方法切入一些增强的代码,会创建一些动态代理的对象,让你对那些目标对象的访问,先经过动态代理对象做一些增强的代码,然后再调用你的目标对象的方法

Spring常用的注入方式有哪些?

Spring通过DI(依赖注入)实现IOC(控制反转),常用的注入方式主要有三种:
(1)构造方法注入
(2)setter注入
(3)基于注解的注入

Spring的事务实现原理是什么?能聊聊你对事务传播机制的理解吗?

事务的ACID特性

原子性(Atomicity)

一系列的操作整体不可拆分,要么同时成功,要么同时失败

一致性(Consistency)

数据在事务的前后,业务整体一致

隔离性(Isolation)

事务之间互相隔离

持久性(Durabilily)

一旦事务成功,数据一定会落盘在数据库

Spring的事务实现原理

如果说你加了一个@Transactional注解,此时就spring会使用AOP思想,对你的这个方法在执行之前,先去开启事务,执行完毕之后,根据你方法是否报错,来决定回滚还是提交事务

Spring的事务传播行为的理解

Spring的事务传播行为 PROPAGATION 总共有7种,以下例举2种
REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务
REQUIRES_NEW:无论当前存不存在事务,都创建新事务
一般使用最多的是 REQUIRED,也是默认的行为
比如说,我们现在有一段业务逻辑,方法A调用方法B和方法C,我希望的是如果说方法A出错了,此时仅仅回滚方法A和B,不能回滚方法C,那么方法 C 就必须得用 REQUIRES_NEW 传播机制,让它和A、B俩的事务行为是不同的​。如果再此基础上方法 A 还设置了事务超时时间为 30 秒,此行为只会传播给 B,即使 B 又设置了超时时间为 5 秒,但还是会以30秒为准,因为 A 事务的所有设置会传播到和它共用一个事务的方法

Spring的事务传播行为的坑

同一个对象内的事务方法互调失效,因为绕过了代理对象

如果按照上述的情况,方法A调用方法B和方法C,此时 A、B、C方法都在同一个类中,这种情况下 B、C做任何设置都没有用,只会和 A 共用同一事务
因为 Spring 事务的原理是基于 AOP,也就是代理对象来完成的,如果只是在同一个类中方法互调,相当于说只是把方法 B、C 进行了一次复制,粘贴,没有走 AOP 的代理,即便使用 this.B() 的方式也一样,this 也是指当前对象,也不会经过代理

解决Spring的事务传播行为的坑,使用代理对象

在这里插入图片描述

如果是本类方法互调,需要完成上述的情况,则可以使用 AopContext 生成动态代理对象来调用
注意:这里不能直接通过 @ Autowired 注解来注入本类的 OrderService,这样就会产生 Spring Bean的循环依赖问题
使用 AopContext 步骤
添加 spring-boot-starter-aop 的依赖
在启动类上添加 @ EnableAspectJAutoProxy(exposeProxy = true) 注解,并设置exposeProxy为true
这样就能如图上所展示的方式,拿到本类的代理对象进行调用

⬇⬇⬇更多面试题请看⬇⬇⬇⬇
更多面试题集

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://JAVA.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <display-name>springMVC</display-name> <welcome-file-list> <welcome-file>/WEB-INF/jsp/login.jsp</welcome-file> </welcome-file-list> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-mybatis.xml</param-value> </context-param> <filter> <filter-name>encodingFilter</filter-name> <filter-class> org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>classpath:log4j.properties</param-value> </context-param> <context-param> <param-name>webAppRootKey</param-name> <param-value>keshe_C12_09.root</param-value> </context-param> <listener> <listener-class> org.springframework.web.util.Log4jConfigListener </listener-class> </listener> </web-app>
07-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值