事务是什么?在MySQL中是怎么去开启,提交,回滚事务的。
- 事务是一组操作的集合,这些操作要么全部成功,要么全部失败;
- 在MySql中事务是默认提交的(每一条SQL语句开启一个事务);
- 在MySql中手动开启、提交、回滚事务:
在Spring中怎么管理事务,用什么注解,在那个层次进行使用可以有效管理事务
- 在Spring中可以使用@Transactional注解来管理事务;
- 在service层添加事务注解(因为事务所控制的是一组操作的集合,而只有在业务层才会存在一个业务功能包含多个数据访问操作)
事务管理时规则:如果方法能够正常执行完自动提交事务,如果出现异常自动回滚事物。事务默认识别的异常是运行时异常,如果想要识别到编译时异常从而实现回滚,该怎么操作?
- 在@Transactional注解上添加rollbackFor这个属性可以指定出现何种异常类型回滚事务
@Transactional(rollbackFor=Exception.class)
事务的传播方式有哪些,含义是怎样?
AOP叫做什么,有什么作用?举一个5岁孩子就能理解的例子?
- AOP英文全称:Aspect Oriented Programming(面向切面编程、面向方面编程)面向切面编程其实就是面向特定方法编程;
- AOP的作用:在程序运行期间在不修改源代码的基础上对已有方法进行增强(无侵入性: 解耦)
小明玩游戏时,我们可以在每次他攻击怪兽之前和之后记录攻击次数。这样,我们可以知道他一共攻击了多少次怪兽。这就是AOP的作用,它可以在不改变原有游戏逻辑的情况下,添加额外的功能
如果要完成一个AOP的入门案例,需要有哪些步骤?
1、导入AOP起步依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2、定义切面类类中编写公共代码(统计执行耗时操作)
3、标识当前类是一个AOP类,并被Spring容器管理
4、配置公共代码作用于哪些目标方法
5、执行目标方法
@Component //该注解表示当前类被Spring容器管理
@Aspect //该注解表示当前类为切面类
@Slf4j //日志依赖
public class TimeAspect {
@Around("execution(* com.itheima.service.*.*(..))")
public Object recordTime(ProceedingJoinPoint pjp) throws Throwable {
//记录方法执行开始时间
long begin = System.currentTimeMillis();
//执行原始方法
Object result = pjp.proceed();
//记录方法执行结束时间
long end = System.currentTimeMillis();
//计算方法执行耗时
log.info(pjp.getSignature()+"执行耗时: {}毫秒",end-begin);
return result; //返回原始方法执行结果
}
}
AOP的概念理解:连接点,通知,切入点,切面 ?
连接点:JoinPoint,可以被AOP控制的方法(需要被增强功能的原始方法)
通知:Advice,指那些重复的逻辑,也就是共性功能(对原始方法功能进行增强的代码)
切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用(筛选需要被增强的方法)
切面:Aspect,描述通知与切入点的对应关系(通知+切入点)
通知有哪些类型?
@Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行;
@Before:前置通知,此注解标注的通知方法在目标方法前被执行;
@After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行;
@AfterReturning : 返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行;
@AfterThrowing : 异常后通知,此注解标注的通知方法发生异常后执行;
如果有不同切面的通知,增强相同的方法,执行顺序是怎样的?
默认按照切面类的类名字母排序:
目标方法前的通知方法:字母排名靠前的先执行
目标方法后的通知方法:字母排名靠前的后执行
如果我们想控制通知的执行顺序有两种方式:
1. 修改切面类的类名(这种方式非常繁琐、而且不便管理)
2. 使用Spring提供的@Order注解
使用@Order注解:注解中属性值小的先执行
使用@Order注解:注解中属性值大的后执行
切点表达式有几种,具体怎么定义?
1、execution(……):根据方法的签名来匹配
execution主要根据方法的返回值、包名、类名、方法名、方法参数等信息来匹配,语法为:
execution(访问修饰符? 返回值 包名.类名.?方法名(方法参数) throws 异常?)
其中带`?`的表示可以省略的部分
访问修饰符:可省略(比如: public、protected)
包名.类名: 可省略
throws 异常:可省略(注意是方法上声明抛出的异常,不是实际抛出的异常)
示例:
@Before("execution(void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))")
可以使用通配符描述切入点
`*` :单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数,也可以通配包、类、方法名的一部分
`..` :多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数
切入点表达式的语法规则:
- 方法的修饰符可以省略
- 返回值可以使用`*`号代替(任意返回值类型)
- 包名可以使用`*`号代替,代表任意包(一层包使用一个`*`)
- 使用`..`配置包名,标识此包以及此包下的所有子包
- 类名可以使用`*`号代替,标识任意类
- 方法名可以使用`*`号代替,表示任意方法
- 可以使用`..`配置参数,任意参数
注意事项:
根据业务需要,可以使用 且(&&)、或(||)、非(!) 来组合比较复杂的切入点表达式。
2、@annotation(……) :根据注解匹配
实现步骤:
-
编写自定义注解
-
在业务类要做为连接点的方法上添加自定义注解
自定义注解:MyLog
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
}
如果有多个通知的切点表达式一样,怎么抽取?
使用@PointCut注解进行抽取:
连接点是什么可以获取哪些信息?
连接点可以简单理解为可以被AOP控制的方法,在SpringAOP当中,连接点又特指方法的执行;
在Spring中用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名、方法名、方法参数等。
对于@Around通知,获取连接点信息只能使用ProceedingJoinPoint类型
对于其他四种通知,获取连接点信息只能使用JoinPoint,它是ProceedingJoinPoint的父类型
//环绕通知
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
//获取执行的目标方法全类类名
String name = pjp.getTarget().getClass().getName();
log.info("目标类名:{}",name);
//目标方法名
String methodName = pjp.getSignature().getName();
log.info("目标方法名:{}",methodName);
//获取方法执行时需要的参数(实参)
Object[] args = pjp.getArgs();
log.info("目标方法参数:{}", Arrays.toString(args));