AOP的介绍
AOP,指面向切面编程(Aspect Oriented Programming),是一种编程思想,在实际应用中是对OOP的有效补充。
在OOP中,模块化的核心单元是类,在AOP中,模块化的核心单元是切面(Aspect),切面中封装了处理逻辑的具体的代码。
AOP的作用
首先介绍一下AOP的产生背景
-
应用程序中的处理逻辑可以分为两类:核心关注点 和 横切关注点。
-
核心关注点指某项业务的核心处理逻辑。而横切关注点指那些会被多个业务重复调用,但是和具体业务关系不大的模块,例如日志模块,性能统计模块,事务管理模块,安全验证模块等这些模块因为aop而变得更加好维护和编写
-
AOP可以将横切关注点的内容封装在Aspect内部,并注入到所需的地方,有效实现核心关注点和横切关注点的解耦,提高了程序的可扩展性和可维护性,提高了开发效率。
其次AOP带来的影响,提高应用程序的开发效率,可扩展性,以及可维护性
下面来一段AOP简单应用的代码
/**
* 系统日志添加的切面类
*
* @author lax
* @date $(DATE) - $(TIME)
*/
@Aspect //这个注解的作用是声明为切面类
@Component //将这个类交给Spring管理
public class SysLogAspect {
/**
*持久层操作方法
*/
@Autowired
SysLogMapper sysLogMapper;
/**
* 切面方法处理 日志的添加功能
* 以下是我的理解
* Around注解的意思是将方法内的逻辑环绕某块区域的代码上面,
* value="excution(* 某块全区域)" 这是声明模块区域
*其中&&annotation(log)的作用是在选定的执行范围内要有要有一个注解,这个注解的类型在方法参数名中要有体现
*
* @param proceedingJoinPoint 切面链接点
* @param logAnno 切面注解
* @return 返回值执行那个方法的返回值, 有就返回有, 没有就返回null
* @throws Throwable 执行方法要抛出的异常
*/
@Around(value = "execution(* com.lax.subsystem.service.impl.*.*(..))&&@annotation(logAnno)")
public Object logAdd(ProceedingJoinPoint proceedingJoinPoint, SysLogAnnotation logAnno) throws Throwable {
// 纪录开始时间
long st = System.currentTimeMillis();
// 调用目标方法
Object result = proceedingJoinPoint.proceed();
// 纪录结束时间
long end = System.currentTimeMillis();
long time = end - st;
// 获取执行方法的中文操作名
String operation = logAnno.operation();
// 调用保存方法
addSysLog(proceedingJoinPoint, time, operation);
return result;
}
/**
* 添加日志数据的处理
*
* @param proceedingJoinPoint 切面链接点的处理
* @param time 执行方法耗时
* @param operation 执行方法的中文名字
* @throws JsonProcessingException 抛出的异常
*/
public void addSysLog(ProceedingJoinPoint proceedingJoinPoint, long time, String operation) throws JsonProcessingException {
// 收集日志信息
// username-> 通过工具获取
String username = UserUtils.getUsername();
//operation ->通过自定义注解实现
// 获取Class类->类名
String className = proceedingJoinPoint.getClass().getName();
// 获取方法签名->方法名
String method = className + "." + proceedingJoinPoint.getSignature().getName();
// 获取执行方法Objec类型的的参数数组对象
Object[] paramsObj = proceedingJoinPoint.getArgs();
// 将Object对象的参数数组转成String类型对象的数组对象
String params = new ObjectMapper().writeValueAsString(paramsObj);
// ip -> 通过工具类获取
String ip = IpUtils.getIpAddr();
// 创建日志对象
Date createdTime;
// 创建新的日志对象
SysLogDO sysLogDo = new SysLogDO(null, username, operation, method
, params, time, ip, null);
// 将新的日志添加到持久层里面
sysLogMapper.insertSysLog(sysLogDo);
}
}
事务的传播机制propagation
1.默认值为Propagation.REQUIRED当前有事物开启,就不新建事务,如果没有就新建事务