Spring-boot 集成sofa 加入 aop切面编程
AOP的核心概念:
1、横切关注点
对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
2、切面(aspect)
类是对物体特征的抽象,切面就是对横切关注点的抽象
3、连接点(join point)
被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
4、切点(pointcut)
对一组连接点(方法)进行拦截的定义,用execution
5、通知(advice)
所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类
6、目标对象
代理的目标对象(核心业务对象)
7、织入(weave)
将切面应用到目标对象并导致代理对象创建的过程
8、引入(introduction)
主要方法
@Aspect:作用在类上,表示该类是一个切面。
@After 通知方法会在目标方法返回或抛出异常后调用
@AfterReturning 通知方法会在目标方法返回后调用
@AfterThrowing 通知方法会在目标方法抛出异常后调用
@Around 通知方法会将目标方法封装起来
@Before 通知方法会在目标方法调用之前执行
核心方法
ProceedingJoinPoint 子类
JoinPoint 父类
- JoinPoint
java.lang.Object[] getArgs():获取连接点方法运行时的入参列表;
Signature getSignature() :获取连接点的方法签名对象;
java.lang.Object getTarget() :获取连接点所在的目标对象;
java.lang.Object getThis() :获取代理对象本身;
- ProceedingJoinPoint
ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法:
java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法;
java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的入参替换原来的入参。
常用方法
joinPoint.proceed(joinPoint.getArgs()); //执行当前程序
joinPoint.getTarget().getClass().getName() //获取调用的类名
joinPoint.getSignature().getName() //获取调用的方法名
pmo.xml中加入aop包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
创建aop
@Component
@Aspect
public class AopDemoAspect {
}
创建切点
//Service层切点
@Pointcut("execution(* com.tl.hello.Controller..*.*(..))")
public void serviceAspect() {
}
创建 在目标方法调用之前执行 @Before
/**
* 通知方法会在目标方法调用之前执行
*
* @param joinPoint
*/
@Before("serviceAspect()")
public void beforeExec(JoinPoint joinPoint) {
List<Object> filterArgs = new ArrayList<>();
String params = null;
try {
if(joinPoint.getArgs()!=null) {
Arrays.stream(joinPoint.getArgs()).forEach(arg -> {
if (!(arg instanceof HttpServletRequest || arg instanceof HttpServletResponse)) {
filterArgs.add(arg);
}
});
}
params = (filterArgs.size()==0)? "": filterArgs.toString();
}catch (Exception e) {
params = filterArgs+"";
}
System.out.println("已经记录下操作日志@Before 方法执行前" + params);
}
创建 在目标方法返回或抛出异常后调用 @After
/**
* 通知方法会在目标方法返回或抛出异常后调用
*
* @param joinPoint
*/
@After("serviceAspect()")
public void afterExec(JoinPoint joinPoint) {
System.out.println("已经记录下操作日志@After 方法执行后");
}
创建 在目标方法正常返回后调用的@AfterReturning
/**
* 通知方法会在目标方法返回后调用
*
* @param joinPoint
*/
@AfterReturning("serviceAspect()")
public void afterReturningExec(JoinPoint joinPoint) {
System.out.println("已经记录下操作日志@AfterReturning 方法执行后");
}
创建 在目标方法异常返回后调用的@AfterThrowing
/**
* 通知方法会在目标方法抛出异常后调用
* @param joinPoint
*/
@AfterThrowing("serviceAspect()")
public void afterThrowingExec(JoinPoint joinPoint) {
System.out.println("已经记录下操作日志@AfterThrowing 方法执行后");
}
最后创建围绕目标方法的方法@Around
/**
* 通知方法会将目标方法封装起来
*
* @param pjp
* @throws Throwable
*/
@Around("serviceAspect()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("已经记录下操作日志@Around 方法执行前");
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
String className = pjp.getTarget().getClass().getName();
String methodName = pjp.getSignature().getName();
getServiceMthodDescription(pjp);
System.out.println("className:" + className);
System.out.println("methodName:" + methodName);
//调用实际的方法
Object o = pjp.proceed(pjp.getArgs());
System.out.println("已经记录下操作日志@Around 方法执行后");
return o;
}
工程下载地址 https://download.csdn.net/download/kevin2562/10691520