美文网首页
使用注解实现aop

使用注解实现aop

作者: kayabu | 来源:发表于2018-10-03 11:35 被阅读0次
    1. 创建切面类
    @Aspect  
    @Component  
    public class LogAspect {  
        @Pointcut("execution(public * com.example.controller.*.*(..))")  
        public void webLog(){}  
      
        @Before("webLog()")  
        public void deBefore(JoinPoint joinPoint) throws Throwable {  
            // 接收到请求,记录请求内容  
            ServletRequestAttributes attributes = 
    (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();  
            HttpServletRequest request = attributes.getRequest();  
            // 记录下请求内容  
            System.out.println("URL : " + request.getRequestURL().toString());  
            System.out.println("HTTP_METHOD : " + request.getMethod());  
            System.out.println("IP : " + request.getRemoteAddr());  
            System.out.println("CLASS_METHOD : " +
             joinPoint.getSignature().getDeclaringTypeName() + 
            "." + joinPoint.getSignature().getName());  
            System.out.println("ARGS : " + Arrays.toString(joinPoint.getArgs()));  
      
        }  
      
        @AfterReturning(returning = "ret", pointcut = "webLog()")  
        public void doAfterReturning(Object ret) throws Throwable {  
            // 处理完请求,返回内容  
            System.out.println("方法的返回值 : " + ret);  
        }  
      
        //后置异常通知  
        @AfterThrowing("webLog()")  
        public void throwss(JoinPoint jp){  
            System.out.println("方法异常时执行.....");  
        }  
      
        //后置最终通知,final增强,不管是抛出异常或者正常退出都会执行  
        @After("webLog()")  
        public void after(JoinPoint jp){  
            System.out.println("方法最后执行.....");  
        }  
      
        //环绕通知,环绕增强,相当于MethodInterceptor  
        @Around("webLog()")  
        public Object arround(ProceedingJoinPoint pjp) {  
            System.out.println("方法环绕start.....");  
            try {  
                Object o =  pjp.proceed();  
                System.out.println("方法环绕proceed,结果是 :" + o);  
                return o;  
            } catch (Throwable e) {  
                e.printStackTrace();  
                return null;  
            }  
        }  
    }  
    
    1. aop注解说明
    • @Aspect:标识为切面类,为容器识别
    • @Before:前置增强,方法执行前执行
    • @AfterReturning:后置增强,方法返回时执行
    • @After:后置增强,方法抛出异常或正常退出时执行
    • @Around:环绕增强
    1. 方法说明
    • 除了@Around外,每个方法里都可以加或者不加参数JoinPoint,如果有用JoinPoint的地方就加,不加也可以
    • JoinPoint里包含了类名、被切面的方法名,参数等属性,可供读取使用。
    • @Around参数必须为ProceedingJoinPoint,pjp.proceed相应于执行被切面的方法。
    • @AfterReturning方法里,可以加returning = “XXX”,XXX即为在controller里方法的返回值,本例中的返回值是“first controller”。
    • @AfterThrowing方法里,可以加throwing = "XXX",供读取异常信息,如本例中可以改为:
        @AfterThrowing(throwing = "ex", pointcut = "webLog()")  
        public void throwss(JoinPoint jp, Exception ex){  
            System.out.println("方法异常时执行.....");  
        } 
    
    1. 关于切入点
      execution函数用于匹配方法执行的连接点,语法为:
      execution(方法修饰符(可选) 返回类型 方法名 参数 异常模式(可选))

    参数部分允许使用通配符:

    • * 匹配任意字符,但只能匹配一个元素
    • .. 匹配任意字符,可以匹配任意多个元素,表示类时,必须和*联合使用
    • + 必须跟在类名后面,如Horseman+,表示类本身和继承或扩展指定类的所有类

    其他切入点注解:

    • @annotation:表示标注了指定注解的目标类方法 @annotation(org.springframework.transaction.annotation.Transactional) 表示标注了@Transactional的方法
    • @args:通过目标类方法的参数类型指定切点
      @args(org.springframework.stereotype.Service) 表示有且仅有一个标注了@Service的类参数的方法
    • @whthin:通过类名指定切点
      @with(examples.chap03.Horseman),表示Horseman的所有方法
    • @target:通过类名指定,同时包含所有子类
      @target(examples.chap03.Horseman) 且Elephantman extends Horseman,则两个类的所有方法都匹配

    运算符:

    • &&
      @execution(* chop(..)) && @target(Horseman) 表示Horseman及其子类的chop方法
    • ||
      @execution(* chop(..)) || @args(String) 表示名称为chop的方法或者有一个String型参数的方法
    • !
      @execution(* chop(..)) and @!args(String) 表示名称为chop的方法但是不能是只有一个String型参数的方法

    大部分情况下,我们需要指定顺序,最简单的方式就是在Aspect切面类上加上@Order(1)注解即可,order越小最先执行,也就是位于最外层。像一些全局处理的就可以把order设小一点,具体到某个细节的就设大一点。

    相关文章

      网友评论

          本文标题:使用注解实现aop

          本文链接:https://www.haomeiwen.com/subject/ayyzoftx.html