AOP简单理解和应用

AOP(面向切面编程),实际就是代理的一个应用,常用的场景有日志、事务、缓存等,分为静态代理和动态代理。

他们的区别是静态代理只能作用在方法上,且代理类是手动编写,常见的就是使用AspectJ,静态代理是在编译期织入。

而动态代理作用域更广泛,可以在属性,方法,构造器等上插入,常用的是cglib,和jdk,动态代理是在运行期枳织入。

cglib和jdk的区别是jdk必须要有实现类,而cglib是生成一个继承类作为代理类。

他们的都是字节码增强

下面简单介绍一下AspectJ:

AspectJ 支持 5 种类型的通知注解:

@Before:前置通知,在方法执行之前执行

@After:后置通知,在方法执行之后执行 (无论是否发生异常都会执行)

@AfterRunning:返回通知,在方法返回结果之后执行

@AfterThrowing:异常通知,在方法抛出异常之后

@Around:环绕通知,围绕着方法执行

例子(接口日志异步入库):


@Aspect
@Component
public class LogAspect {

  @Autowired
  private SaveLogService saveLogService;

  // 定义切点
  @Pointcut("@annotation(com.zdww.cd.sx.config.MyLog)")
  public void LogPointCut() {
  }

  //切面(通知和切点) 配置通知
  @After("LogPointCut()")
  // 一共有五种通知,after在方法之后执行
  public void saveOperation(JoinPoint joinPoint) {

    //用于保存日志
    com.zdww.cd.sx.pojo.MyLog log = new com.zdww.cd.sx.pojo.MyLog();

    //从连接点处通过反射机制获取连接点处的方法签名对象
    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    //获取连接点所在的方法
    Method method = signature.getMethod();
    //获取操作方法上的MyLog注解的值
    MyLog myLog = method.getAnnotation(MyLog.class);
    if (myLog != null) {
      String operation = myLog.operation();
      log.setOperation(operation);
      String type = myLog.type();
      log.setType(type);
    }
    HttpServletRequest request = ((ServletRequestAttributes) Objects
        .requireNonNull(RequestContextHolder
            .getRequestAttributes())).getRequest();
    String requestURL = request.getRequestURL().toString();
    log.setUrl(requestURL);
    String ip = IPUtil.getIP(request);
    log.setLoginIp(ip);
    Date now = new Date();
    log.setCreateTime(now);
    User user = (User) request.getSession().getAttribute("user");
    if (user != null) {
      String userId = user.getAccount();
      String userName = user.getUsername();
      log.setUserId(userId);
      log.setUserName(userName);
      saveLogService.saveLog(log);
    }
  }
}
获取切入方法对象三种方法:
 

1.通过反射机制获取切入点目标类的方法

 
public void invoke(JoinPoint joinPoint) throws Throwable{  
  
//登录拦截  
  
MethodInvocationProceedingJoinPoint methodPoint = (MethodInvocationProceedingJoinPoint)joinPoint;  
  
Field proxy = methodPoint.getClass().getDeclaredField("methodInvocation");  
  
proxy.setAccessible(true);  
  
ReflectiveMethodInvocation j = (ReflectiveMethodInvocation) proxy.get(methodPoint);  
  
Method method = j.getMethod();  
  
Login login = method.getAnnotation(Login.class);  
  
}  



 

 

2.通过JoinPoint的getTarget()获取连接点所在的目标对象

 
 
public void invoke(JoinPoint joinPoint) throws Throwable{  
  
//拦截的实体类  
  
Object target = joinPoint.getTarget();  
  
//拦截的方法名称  
  
String methodName = joinPoint.getSignature().getName();  
  
//拦截的方法参数  
  
Object[] argsa = joinPoint.getArgs();  
  
//拦截的放参数类型  
  
Class[] parameterTypes = ((MethodSignature)joinPoint.getSignature()).getMethod().getParameterTypes();  
  
Method method = target.getClass().getMethod(methodName, parameterTypes);  
  
Login login = method.getAnnotation(Login.class);  
  
}  



 

3.通过JoinPoint的getSignature()获取连接点的方法签名对象

 
public void invoke(JoinPoint joinPoint) throws Throwable{  
  
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();  
  
Method method = methodSignature.getMethod();  
  
Login login = method.getAnnotation(Login.class);  
  
}  

 

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值