【JavaGuide面试总结】Spring篇·中
- 1.谈谈自己对于 AOP 的了解
- 2.Spring AOP 和 AspectJ AOP 有什么区别?
- 3.AspectJ 定义的通知类型有哪些?
- 4.Spring AOP多个切面的执行顺序如何控制?
- 5.说说自己对于 Spring MVC 了解?
- 6.Spring MVC 的核心组件有哪些?
- 7.SpringMVC 工作原理了解吗?
- 8.统一异常处理怎么做?
- 9.Spring 管理事务的方式有几种?
- 10.Spring 事务中的隔离级别有哪几种?
1.谈谈自己对于 AOP 的了解
AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib 生成一个被代理对象的子类来作为代理
2.Spring AOP 和 AspectJ AOP 有什么区别?
Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理,而 AspectJ 基于字节码操作
Spring AOP 已经集成了 AspectJ,Spring AOP的实现本质上使用的是AspectJ的注解🦉
如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比 Spring AOP 快很多。
3.AspectJ 定义的通知类型有哪些?
- Before(前置通知):目标对象的方法调用之前触发
- After (后置通知):目标对象的方法调用之后触发
- AfterReturning(返回通知):目标对象的方法调用完成,在返回结果值之后触发
- AfterThrowing(异常通知) :目标对象的方法运行中抛出 / 触发异常后触发。AfterReturning 和 AfterThrowing 两者互斥。如果方法调用成功无异常,则会有返回值;如果方法抛出了异常,则不会有返回值。
- Around (环绕通知):编程式控制目标对象的方法调用。环绕通知是所有通知类型中可操作范围最大的一种,因为它可以直接拿到目标对象,以及要执行的方法,所以环绕通知可以任意的在目标对象的方法调用前后搞事,甚至不调用目标对象的方法
将上面的所有通知类型写入同一个切面中,它的执行顺序为:
代码演示:
@Aspect
@Component
public class SysTimeAspect {
/**
* 切入点
*/
@Pointcut("bean(sysMenuServiceImpl)")
public void doTime() {}
@Before("doTime()")
public void doBefore(JoinPoint jp) {
System.out.println("time doBefore()");
}
@After("doTime()")
public void doAfter() { // 其实类似于finally{}代码块
System.out.println("time doAfter()");
}
/**
* 核心业务正常结束时执行
* 说明:假如有after,先执行after,再执行returning
*/
@AfterReturning("doTime()")
public void doAfterReturning() {
System.out.println("time doAfterReturning");
}
/**
* 核心业务出现异常时执行
* 说明:假如有after,先执行after,再执行Throwing
*/
@AfterThrowing("doTime()")
public void doAfterThrowing() {
System.out.println("time doAfterThrowing");
}
@Around("doTime()")
public Object doAround(ProceedingJoinPoint jp) throws Throwable {
System.out.println("doAround.before");
try {
Object obj=jp.proceed();
return obj;
} catch(Throwable e) {
System.out.println("doAround.error-->"+e.getMessage());
throw e;
} finally {
System.out.println("doAround.after");
}
}
}
4.Spring AOP多个切面的执行顺序如何控制?
- 通常使用
@Order
注解直接定义切面顺序
// 值越小优先级越高
@Order(3)
@Component
@Aspect
public class LoggingAspect {
- 实现
Ordered
接口重写getOrder
方法
@Component
@Aspect
public class LoggingAspect implements Ordered {
// ....
@Override
public int getOrder() {
// 返回值越小优先级越高
return 1;
}
}
5.说说自己对于 Spring MVC 了解?
MVC 是模型(Model)、视图(View)、控制器(Controller)的简写,其核心思想是通过将业务逻辑、数据、显示分离来组织代码。
MVC 是一种设计模式,Spring MVC 是一款很优秀的 MVC 框架。Spring MVC 可以帮助我们进行更简洁的 Web 层的开发,并且它天生与 Spring 框架集成。Spring MVC 下我们一般把后端项目分为 Service 层(处理业务)、Dao 层(数据库操作)、Entity 层(实体类)、Controller 层(控制层,返回数据给前台页面)。
6.Spring MVC 的核心组件有哪些?
DispatcherServlet
:核心的中央处理器,负责接收请求、分发,并给予客户端响应。HandlerMapping
:处理器映射器,根据 uri 去匹配查找能处理的Handler
,并会将请求涉及到的拦截器和Handler
一起封装。HandlerAdapter
:处理器适配器,根据HandlerMapping
找到的Handler
,适配执行对应的Handler
;Handler
:请求处理器,处理实际请求的处理器。ViewResolver
:视图解析器,根据Handler
返回的逻辑视图 / 视图,解析并渲染真正的视图,并传递给DispatcherServlet
响应客户端
7.SpringMVC 工作原理了解吗?
Spring MVC 原理如下图所示:
- 客户端(浏览器)发送请求,
DispatcherServlet
拦截请求。 DispatcherServlet
根据请求信息调用HandlerMapping
。HandlerMapping
根据 uri 去匹配查找能处理的Handler
(也就是我们平常说的Controller
控制器) ,并会将请求涉及到的拦截器和Handler
一起封装。DispatcherServlet
调用HandlerAdapter
适配执行Handler
。Handler
完成对用户请求的处理后,会返回一个ModelAndView
对象给DispatcherServlet
,ModelAndView
顾名思义,包含了数据模型以及相应的视图的信息。Model
是返回的数据对象,View
是个逻辑上的View
。ViewResolver
会根据逻辑View
查找实际的View
。DispaterServlet
把返回的Model
传给View
(视图渲染)。- 把
View
返回给请求者(浏览器)
8.统一异常处理怎么做?
推荐使用注解的方式统一异常处理,具体会使用到 @ControllerAdvice
+ @ExceptionHandler
这两个注解 。
@ControllerAdvice
注解同样具有注册bean的功能!🐤
例子:
@ControllerAdvice
public class ExceptionController {
/**
* 数学运算异常和空指针异常的处理
* @param e
* @param model
* @return fuck!
*/
@ExceptionHandler(value = {ArithmeticException.class, NullPointerException.class})
public String testExceptionHandler(Exception e, Model model) {
model.addAttribute("e", e);
return "fuck!";
}
}
9.Spring 管理事务的方式有几种?
编程式事务 : 在代码中硬编码(不推荐使用) : 通过 TransactionTemplate
或者 Transacti onManager
手动管理事务,实际应用中很少使用,但是对于你理解 Spring 事务管理原理有帮助。
声明式事务 : 在 XML 配置文件中配置或者直接基于注解(推荐使用) : 实际是通过 AOP 实现(基于@Transactional
的全注解方式使用最多)
10.Spring 事务中的隔离级别有哪几种?
TransactionDefinition
接口中定义了五个表示隔离级别的常量:
public interface TransactionDefinition {
......
int ISOLATION_DEFAULT = -1;
int ISOLATION_READ_UNCOMMITTED = 1;
int ISOLATION_READ_COMMITTED = 2;
int ISOLATION_REPEATABLE_READ = 4;
int ISOLATION_SERIALIZABLE = 8;
......
}
TransactionDefinition.ISOLATION_DEFAULT
:使用后端数据库默认的隔离级别,MySQL 默认采用的REPEATABLE_READ
隔离级别(默认隔离级别)TransactionDefinition.ISOLATION_READ_UNCOMMITTED
:最低的隔离级别,使用这个隔离级别很少,因为它允许读取尚未提交的数据变更,*可能会导致脏读、幻读或不可重复读(读未提交)TransactionDefinition.ISOLATION_READ_COMMITTED
: 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生(读已提交)TransactionDefinition.ISOLATION_REPEATABLE_READ
: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生TransactionDefinition.ISOLATION_SERIALIZABLE
: 最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。