背景
aop的概念很多,比如切点,通知,连接点,引入,织入等;实际上这是一种约定的流程;
约定编程
https://github.com/carterbrother/springbootpractice/tree/master/demo-aop
aop编程
也是按照一定规则,按照一定 流程来约定编程的;
典型场景
- 数据库事物
提取固定 流程,把变化的部分织入到流程中即可;
概念
连接点(join point) : 即方法
切点 (point cut): 连接点的范围,哪些方法;
通知(advice): 分为前置通知,后置通知,环绕通知,正常返回通知,异常返回通知
目标对象(target) :被代理对象
引入(introduction): 引入新的类和方法,增强现有的bean的功能
织入(weaving): 通过代理技术,为原有对象生成代理对象
切面(aspect) : 可以定义切点,各类通知和引用的内容
springboot的aop的使用
@Aspect 申明切面
通知里面放切点:
@Before 前置通知
@After 后置通知
@AfterReturn
@AfterThrowning
@Around
@Pointcut 定义切点
切点的指示器:
通知中的参数:
ProceedingJoinPoint jp 连接点信息
jp.proceed();//执行原来的方法
spring采用两种动态代理方式,jdk的动态代理和cglib的动态代理,如果被代理类没有实现接口,spring会切换为cglib的动态代理;
多个切面,使用@Order(value=x) 来定义顺序,前置通知从升序执行,后置通知降序执行;
例子:
package com.lifesense.ihs.tianansp.admin.interceptor;
import com.google.common.base.Strings;
import com.lifesense.ihs.tianansp.admin.core.TaAdminRestContext;
import com.lifesense.opensource.commons.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;
import java.lang.reflect.Method;
/**
* aop
*/
@Aspect
@Service
@Order(0)
@Slf4j
public class ServiceInterceptor {
@Pointcut("execution(public * com.lifesense.ihs.**.admin.manager..*.*(..))")
public void pointcut() {
}
private String serviceName() {
return "tiananspadmin";
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
StopWatch stopWatch = new StopWatch();
Method method = ((MethodSignature) pjp.getSignature()).getMethod();
final String methodName = method.getDeclaringClass().getCanonicalName().concat(".").concat(method.getName());
stopWatch.start(methodName);
Object[] args = pjp.getArgs();
String requestId = TaAdminRestContext.get().getRequestId();
Object returnObj = null;
try {
returnObj = pjp.proceed();
} catch (Exception ex) {
String message = String.format("[%s]服务发生系统错误:%s",this.serviceName(),ex.getMessage());
log.error("{},method:{},args:{},ServiceContext:{}",message,methodName,JsonUtils.toJson(args),TaAdminRestContext.get(),ex);
throw ex;
} finally {
stopWatch.stop();
if (log.isDebugEnabled()) {
log.debug("timecost_requestId:{},returnObj:{},\n{}:",requestId,JsonUtils.toJson(returnObj),stopWatch.prettyPrint());
}
}
return returnObj;
}
}
原创不易,转载请注明出处。