美文网首页
浅谈java切面

浅谈java切面

作者: 七秒的记忆_d4a7 | 来源:发表于2020-10-13 11:43 被阅读0次

    一、切面定义

    切面 = 切点+通知

    • 切点(pointcut): 定义执行切面的入口点 ,这里切入点指示符

    • 通知:interceptor实现切面逻辑

    二、切入点指示符的含义及使用(execution、within、this、target等)

    • execution:用于匹配方法执行的连接点 execution(* com.test.method.des...(..))
    • execution() 表达式的主体
    • 第一个“*”符号 表示返回值的类型任意
    • com.test.method.des AOP所切的服务的包名,即,需要进行横切的业务类
    • 包名后面的“..” 表示当前包及子包
    • 第二个“” 表示类名,即所有类
    • .*(..) 表示任何方法名,括号表示参数,两个点表示任何参数类型
    • within:用于匹配指定类型内的方法执行,within比较严格,它是严格匹配被代理对象类型的,不会理会继承关系,例如A继承了接口B,则within("B")不会匹配到A,但是within("B+")可以匹配到A
    • within(cn.java..*) . cn.java包及子包下的任何方法执行
    • within(java..IPointcutService+) . java包或所有子包下IPointcutService类型及子类型的任何方法
    • within(@cn..Secure *) 持有cn..Secure注解的任何类型的任何方法
    • target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配 , 例如A继承了B接口,则使用target("B"),target("A")均可以匹配到A, 我们pointcut 所选取的Join point 的所有者,直白点说就是: 指明拦截的方法属于那个类。
    • this:用于匹配当前AOP代理对象类型的执行方法,注意是AOP代理对象的类型匹配, 我们pointcut 所选取的Join point 的调用的所有者,就是说:方法是在那个类中被调。

    三、切面应用实例

    /**
     * 定义日志注解
     */
    
    package test.anotation;
    
    import java.lang.annotation.*;
    
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface Log {
        String desc() default "打印日志";
    }
    
    
    /**
     * 定义日志切面
     */
    
    
    package test.aspect;
    
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.stereotype.Component;
    import test.anotation.Log;
    
    import java.lang.reflect.Method;
    
    import java.util.Arrays;
    import java.util.List;
    
    @Aspect
    @Component
    public class LogAspect {
    
        /**
         * 标注该方法体为后置通知,当目标方法执行成功后执行该方法体
         */
        @AfterReturning("within(test..*) && @annotation(rl)")
        public void addLogSuccess(JoinPoint jp, Log rl){
            Object[] parames = jp.getArgs();//获取目标方法体参数
            for (int i = 0; i < parames.length; i++) {
                System.out.println(parames[i]);
            }
            System.out.println(jp.getSignature().getName());
            String className = jp.getTarget().getClass().toString();//获取目标类名
            System.out.println("className:" + className);
            className = className.substring(className.indexOf("test"));
            String signature = jp.getSignature().toString();//获取目标方法签名
            System.out.println("signature:" + signature);
            System.out.println(rl.desc());
        }
    
        @Pointcut("@annotation(test.anotation.Log)")
        public void serviceMethodPointcut() {
           //切点
        }
    
        /**
         * 前置通知方法, 匹配test包下所有类的方法
         * 方法的返回值 和 test包下所有的类和方法,以及方法的形参 都抽象了
         * @param point
         * @return
         * @throws Throwable
         */
        @Before("execution(* test..*(..))")
        public void beforeAdvice(JoinPoint point){
            String methodName = point.getSignature().getName();
            List<Object> args = Arrays.asList(point.getArgs());
            System.out.println("@Before 前置通知 : 方法名 【 " + methodName + " 】and args are " + args);
    
        }
    
        /**
         * 环绕通知, 注解切点匹配
         * @param pjp
         * @return
         * @throws Throwable
         */
        @Around("serviceMethodPointcut()")
        public Object interceptor(ProceedingJoinPoint pjp) throws Throwable {
            //通知方法
            String className = pjp.getTarget().getClass().toString();//获取目标类名
            System.out.println("className:" + className);
    
            MethodSignature signature = (MethodSignature) pjp.getSignature();
            Method method = signature.getMethod();
            String methodName = method.getName();
    
            System.out.println("methodName:" + methodName);
    
            return pjp.proceed();
        }
    }
    

    相关文章

      网友评论

          本文标题:浅谈java切面

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