精华内容
下载资源
问答
  • 本文主要介绍JoinPoint的常用方法 原文链接:JoinPoint和ProceedingJoinPoint有啥不一样? 在以一个实际例子演示如何使用注解实现AOP装配时,为了监控应用程序的性能,我们定义一个性能监控的注解: @Target(METHOD)...

    本文主要介绍JoinPoint的常用方法

    原文链接:JoinPoint和ProceedingJoinPoint有啥不一样?

    在以一个实际例子演示如何使用注解实现AOP装配时,为了监控应用程序的性能,我们定义一个性能监控的注解

    @Target(METHOD)
    @Retention(RUNTIME)
    public @interface MetricTime {
        String value();
    }
    

    在需要被监控的关键方法上标注该注解:

    @Component
    public class UserService {
        // 监控register()方法性能:
        @MetricTime("register")
        public User register(String email, String password, String name) {
            ...
        }
        ...
    }
    

    然后,我们定义MetricAspect

    @Component
    @Aspect
    public class MetricAspect {
    
        @Around("@annotation(metricTime)")
        public Object metric(ProceedingJoinPoint joinPoint,MetricTime metricTime) throws Throwable {
            String name = metricTime.value();
            Long startTime = System.currentTimeMillis();
            try{
    //            System.out.println("joinPoint.proceed():  " + joinPoint.proceed());//com.sun.service.User@c055c54
                return joinPoint.proceed(new Object[]{"44444@163.com","dd23423dd","dddd"});
            }finally {
                long time = System.currentTimeMillis() - startTime;
                System.err.println("[Metrics] " + name + ": " + time + "ms");
            }
    
        }
    }
    

    注意metric()方法标注了@Around("@annotation(metricTime)"),它的意思是,符合条件的目标方法是带有@MetricTime注解的方法,因为metric()方法参数类型是MetricTime(注意参数名是metricTime不是MetricTime),我们通过它获取性能监控的名称。

    有了@MetricTime注解,再配合MetricAspect,任何Bean,只要方法标注了@MetricTime注解,就可以自动实现性能监控。

    @AppConfig.java

    @ComponentScan
    @Configuration
    @EnableAspectJAutoProxy
    public class AppConfig {
    
        public static void main(String[] args) throws Exception {
            ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
            UserService userService = (UserService) context.getBean("userService");
            User user = userService.register("333333333@qqqqq.com", "3333333qqaaa", "qqa333");
            System.out.println(user);
            }
    

    运行结果:

    mail service zoneId is init....Asia/Shanghai
    i = 1
    执行成功...
    Welcome, dddd!
    [Metrics] register: 612ms
    User{id=92, email='44444@163.com', password='dd23423dd', name='dddd'}
    
    

    数据库结果:

    数据库

    最终存储到数据库中的并不是:

    User user = userService.register("333333333@qqqqq.com", "3333333qqaaa", "qqa333");
    

    而是metric方法中:

    @Around("@annotation(metricTime)")
        public Object metric(ProceedingJoinPoint joinPoint,MetricTime metricTime) throws Throwable {
            String name = metricTime.value();
            Long startTime = System.currentTimeMillis();
            try{
    //            System.out.println("joinPoint.proceed():  " + joinPoint.proceed());//com.sun.service.User@c055c54
                 return joinPoint.proceed(new Object[]{"44444@163.com","dd23423dd","dddd"}); 
            }finally {
                long time = System.currentTimeMillis() - startTime;
                System.err.println("[Metrics] " + name + ": " + time + "ms");
            }
    
        }
    

    return joinPoint.proceed(new Object[]{"44444@163.com","dd23423dd","dddd"});


    研究一下JoinPoint方法的使用

    AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org.aspectj.lang.ProceedingJoinPoint表示连接点对象,该类是JoinPoint的子接口。任何一个增强方法都可以通过将第一个入参声明为JoinPoint访问到连接点上下文的信息。我们先来了解一下这两个接口的主要方法:

    JoinPoint

    JoinPoint

    JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象,常用api:

    方法名功能
    Signature getSignature()获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息
    Object[] getArgs()获取传入目标方法的参数对象
    Object getTarget()获取被代理的对象
    Object getThis()获取代理对象

    ProceedingJoinPoint

    ProceedingJoinPoint对象是JoinPoint的子接口,该对象只用在@Around的切面方法中, 添加了两个方法.

    方法名功能
    Object proceed() throws Throwable执行目标方法
    Object proceed(Object[] var1) throws Throwable传入的新的参数去执行目标方法

    Demo

    切面类:

    @Aspect
    @Component
    public class aopAspect {
        /**
         * 定义一个切入点表达式,用来确定哪些类需要代理
         * execution(* aopdemo.*.*(..))代表aopdemo包下所有类的所有方法都会被代理
         */
        @Pointcut("execution(* aopdemo.*.*(..))")
        public void declareJoinPointerExpression() {}
     
        /**
         * 前置方法,在目标方法执行前执行
         * @param joinPoint 封装了代理方法信息的对象,若用不到则可以忽略不写
         */
        @Before("declareJoinPointerExpression()")
        public void beforeMethod(JoinPoint joinPoint){
            System.out.println("目标方法名为:" + joinPoint.getSignature().getName());
            System.out.println("目标方法所属类的简单类名:" +        joinPoint.getSignature().getDeclaringType().getSimpleName());
            System.out.println("目标方法所属类的类名:" + joinPoint.getSignature().getDeclaringTypeName());
            System.out.println("目标方法声明类型:" + Modifier.toString(joinPoint.getSignature().getModifiers()));
            //获取传入目标方法的参数
            Object[] args = joinPoint.getArgs();
            for (int i = 0; i < args.length; i++) {
                System.out.println("第" + (i+1) + "个参数为:" + args[i]);
            }
            System.out.println("被代理的对象:" + joinPoint.getTarget());
            System.out.println("代理对象自己:" + joinPoint.getThis());
        }
     
        /**
         * 环绕方法,可自定义目标方法执行的时机
         * @param pjd JoinPoint的子接口,添加了
         *            Object proceed() throws Throwable 执行目标方法
         *            Object proceed(Object[] var1) throws Throwable 传入的新的参数去执行目标方法
         *            两个方法
         * @return 此方法需要返回值,返回值视为目标方法的返回值
         */
        @Around("declareJoinPointerExpression()")
        public Object aroundMethod(ProceedingJoinPoint pjd){
            Object result = null;
     
            try {
                //前置通知
                System.out.println("目标方法执行前...");
                //执行目标方法
                //result = pjd.proeed();
                //用新的参数值执行目标方法
                result = pjd.proceed(new Object[]{"newSpring","newAop"});
                //返回通知
                System.out.println("目标方法返回结果后...");
            } catch (Throwable e) {
                //异常通知
                System.out.println("执行目标方法异常后...");
                throw new RuntimeException(e);
            }
            //后置通知
            System.out.println("目标方法执行后...");
     
            return result;
        }
    }
    
    

    被代理类:

    /**
     * 被代理对象
     */
    @Component
    public class TargetClass {
        /**
         * 拼接两个字符串
         */
        public String joint(String str1, String str2) {
            return str1 + "+" + str2;
        }
    }
    

    测试类:

    public class TestAop {
        @Test
        public void testAOP() {
            //1、创建Spring的IOC的容器
            ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:bean.xml");
     
            //2、从IOC容器中获取bean的实例
            TargetClass targetClass = (TargetClass) ctx.getBean("targetClass");
     
            //3、使用bean
            String result = targetClass.joint("spring","aop");
            System.out.println("result:" + result);
        }
    }
    

    测试结果:

    目标方法执行前...
    目标方法名为:joint
    目标方法所属类的简单类名:TargetClass
    目标方法所属类的类名:aopdemo.TargetClass
    目标方法声明类型:public1个参数为:newSpring
    第2个参数为:newAop
    被代理的对象:aopdemo.TargetClass@4efc180e
    代理对象自己:aopdemo.TargetClass@4efc180e
    目标方法返回结果后...
    目标方法执行后...
    result:newSpring+newAop
    

    Q&A

    Q: 代理对象自己和被代理对象输出的内存地址一样啊楼主!应该就是这样的吗?

    A:不是,所谓代理类其实就是内部调用了目标类的方法,两个不同的对象内存地址不可能一样,上面的目标类和代理类打印调用的是toString(),但是代理类调用的其实是目标类的toString,所以地址一样,但是你如果用==比较是不一样的,也就是false

    展开全文
  • 在AOP编程过程中需要使用到的一个 JoinPoint 接口,用来获取调用的信息,下面是这个接口的代码 // // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // ...

            在AOP编程过程中需要使用到的一个 JoinPoint 接口,用来获取调用的信息,下面是这个接口的代码

            

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by FernFlower decompiler)
    //
    
    package org.aspectj.lang;
    
    import org.aspectj.lang.reflect.SourceLocation;
    
    public interface JoinPoint {
        // 一堆接口的默认字符串变量,暂时不用管
        String METHOD_EXECUTION = "method-execution";
        String METHOD_CALL = "method-call";
        String CONSTRUCTOR_EXECUTION = "constructor-execution";
        String CONSTRUCTOR_CALL = "constructor-call";
        String FIELD_GET = "field-get";
        String FIELD_SET = "field-set";
        String STATICINITIALIZATION = "staticinitialization";
        String PREINITIALIZATION = "preinitialization";
        String INITIALIZATION = "initialization";
        String EXCEPTION_HANDLER = "exception-handler";
        String SYNCHRONIZATION_LOCK = "lock";
        String SYNCHRONIZATION_UNLOCK = "unlock";
        String ADVICE_EXECUTION = "adviceexecution";
    
        // 下面几个方法就是我们需要关注的
    
        // 打印,信息量一般
        String toString();
        // 打印,信息量少
        String toShortString();
        // 打印,信息量多
        String toLongString();
        // 获取代理对象
        Object getThis();
        //  获取被代理的对象
        Object getTarget();
        // 获取切入点获取参数
        Object[] getArgs();
        // Signature ,这是另一个需要着重注意的类,基本上也是获取切入点信息的
        Signature getSignature();
    
        // 切入点所在类文件中的位置
        SourceLocation getSourceLocation();
        // 切入点类型 猜测是上面定义的默认变量中的几个,比如 METHOD_EXECUTION等
        String getKind();
        // 调用静态方法
        JoinPoint.StaticPart getStaticPart();
    
        public interface EnclosingStaticPart extends JoinPoint.StaticPart {
        }
        
        // 展示有哪些静态方法,基本都是上面已有的,也暂时不用管
        public interface StaticPart {
            Signature getSignature();
    
            SourceLocation getSourceLocation();
    
            String getKind();
    
            int getId();
    
            String toString();
    
            String toShortString();
    
            String toLongString();
        }
    }
    

    我们主要关注的就是那几个方法,上面的默认变量不用太关注,下面是实际的测试信息

    切面:

       @After(value = "execution(* com.mz.testSpring.controler.testSpringControler.sayHello(..))")
        public void afterMethod(JoinPoint joinPoint){
            System.out.println("I'm fine ,thank you");
            //JoinPoint测试
            System.out.println("toString:"+joinPoint.toString());
            System.out.println("toShortString:"+joinPoint.toShortString());
            System.out.println("toLongString:"+joinPoint.toLongString());
            System.out.println("getThis:"+joinPoint.getThis().toString());
            System.out.println("getTarget:"+joinPoint.getTarget().toString());
            System.out.println("getArgs:"+ Arrays.toString(joinPoint.getArgs()));
            System.out.println("getSignature:"+joinPoint.getSignature().toString());
            System.out.println("getSourceLocation1:"+joinPoint.getSourceLocation().toString());
            System.out.println("getSourceLocation3:"+joinPoint.getSourceLocation().getWithinType().getName());
            System.out.println("getKind:"+joinPoint.getKind());
            System.out.println("getStaticPart:"+joinPoint.getStaticPart());
    
        }

    原始功能:

        @GetMapping(value = "/testAnno")
        public String sayHello(String name){
           return "Are you ok? "+name;
        }

    调用URL:

    GET http://localhost:8080/test/testAnno?name=Indian frends
    Accept: application/json

    httpClient返回结果(主要是测一下逻辑功能有没有问题,与AOP编程关系不大):

    GET http://localhost:8080/test/testAnno?name=Indian+frends
    
    HTTP/1.1 200 
    Content-Type: application/json;charset=UTF-8
    Content-Length: 25
    Date: Mon, 06 Dec 2021 06:10:20 GMT
    
    Are you ok? Indian frends
    
    Response code: 200; Time: 60ms; Content length: 25 bytes

    切面打印的结果:

    I'm fine ,thank you
    toString:execution(String com.mz.testSpring.controler.testSpringControler.sayHello(String))
    toShortString:execution(testSpringControler.sayHello(..))
    toLongString:execution(public java.lang.String com.mz.testSpring.controler.testSpringControler.sayHello(java.lang.String))
    getThis:com.mz.testSpring.controler.testSpringControler@5368e981
    getTarget:com.mz.testSpring.controler.testSpringControler@5368e981
    getArgs:[Indian frends]
    getSignature:String com.mz.testSpring.controler.testSpringControler.sayHello(String)
    getSourceLocation1:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@1aa60b10
    getSourceLocation3:com.mz.testSpring.controler.testSpringControler
    getKind:method-execution
    getStaticPart:execution(String com.mz.testSpring.controler.testSpringControler.sayHello(String))

    从返回结果我们可以看出来,JoinPoint可以获取原始功能的名称,所在的类,所在的包,参数等。我们获取这些信息之后就可以通过反射来对原始功能进行补充,实现功能的增强,也就是说AOP编程和反射是分不开的。

    展开全文
  • JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象. ProceedingJoinPoint对象是JoinPoint的子接口,该对象只用在@Around的切面方法中 ...

    前言

    上一篇文章讲解了springboot aop 初步完整的使用和整合 这一篇讲解他的接口方法和类

    JoinPoint和ProceedingJoinPoint对象

    1. JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象.

    2. ProceedingJoinPoint对象是JoinPoint的子接口,该对象只用在@Around的切面方法中

    @Aspect
    @Component
    public class aopAspect {
        /**
         * 定义一个切入点表达式,用来确定哪些类需要代理
         * execution(* aopdemo.*.*(..))代表aopdemo包下所有类的所有方法都会被代理
         */
        @Pointcut("execution(* aopdemo.*.*(..))")
        public void declareJoinPointerExpression() {}
    
        /**
         * 前置方法,在目标方法执行前执行
         * @param joinPoint 封装了代理方法信息的对象,若用不到则可以忽略不写
         */
        @Before("declareJoinPointerExpression()")
        public void beforeMethod(JoinPoint joinPoint){
            System.out.println("目标方法名为:" + joinPoint.getSignature().getName());
            System.out.println("目标方法所属类的简单类名:" +        joinPoint.getSignature().getDeclaringType().getSimpleName());
            System.out.println("目标方法所属类的类名:" + joinPoint.getSignature().getDeclaringTypeName());
            System.out.println("目标方法声明类型:" + Modifier.toString(joinPoint.getSignature().getModifiers()));
            //获取传入目标方法的参数
            Object[] args = joinPoint.getArgs();
            for (int i = 0; i < args.length; i++) {
                System.out.println("第" + (i+1) + "个参数为:" + args[i]);
            }
            System.out.println("被代理的对象:" + joinPoint.getTarget());
            System.out.println("代理对象自己:" + joinPoint.getThis());
        }
    
        /**
         * 环绕方法,可自定义目标方法执行的时机
         * @param pjd JoinPoint的子接口,添加了
         *            Object proceed() throws Throwable 执行目标方法
         *            Object proceed(Object[] var1) throws Throwable 传入的新的参数去执行目标方法
         *            两个方法
         * @return 此方法需要返回值,返回值视为目标方法的返回值
         */
        @Around("declareJoinPointerExpression()")
        public Object aroundMethod(ProceedingJoinPoint pjd){
            Object result = null;
    
            try {
                //前置通知
                System.out.println("目标方法执行前...");
                //执行目标方法
                //result = pjd.proeed();
                //用新的参数值执行目标方法
                result = pjd.proceed(new Object[]{"newSpring","newAop"});
                //返回通知
                System.out.println("目标方法返回结果后...");
            } catch (Throwable e) {
                //异常通知
                System.out.println("执行目标方法异常后...");
                throw new RuntimeException(e);
            }
            //后置通知
            System.out.println("目标方法执行后...");
    
            return result;
        }
    }
    

    切点表达式

    1. 在Spring AOP中,连接点始终代表方法的执行。切入点是与连接点匹配的,切入点表达语言是以编程方式描述切入点的方式。

    2. 切入点(Poincut)是定义了在“什么地方”进行切入,哪些连接点会得到通知。显然,切点一定是连接点

    3. 切点是通过@Pointcut注解和切点表达式定义的。@Pointcut注解可以在一个切面内定义可重用的切点。

    execute表达式

    *代表匹配任意修饰符及任意返回值,参数列表中..匹配任意数量的参数

    可以使用&&、||、!、三种运算符来组合切点表达式,表示与或非的关系

    1. 拦截任意公共方法execution(public * *(..))
    2. 拦截以set开头的任意方法execution(* set*(..))
    3. 拦截类或者接口中的方法
    拦截AccountService(类、接口)中定义的所有方法
    execution(* com.xyz.service.AccountService.*(..))
    
    1. 拦截包中定义的方法,不包含子包中的方法
    拦截com.xyz.service包中所有类中任意方法,**不包含**子包中的类
    execution(* com.xyz.service.*.*(..))
    
    1. 拦截包或者子包中定义的方法
    拦截com.xyz.service包或者子包中定义的所有方法
    execution(* com.xyz.service..*.*(..))
    

    通知分类

    @Before

    1. 前置通知: 在方法执行之前执行
    2. 前置通知使用@Before注解 将切入点表达式值作为注解的值

    @After

    1. 后置通知, 在方法执行之后执行
    2. 后置通知使用@After注解 ,在后置通知中,不能访问目标方法执行的结果

    @AfterRunning

    1. 返回通知, 在方法返回结果之后执行
    2. 返回通知使用@AfterRunning注解

    @AfterThrowing

    1. 异常通知, 在方法抛出异常之后执行
    2. 异常通知使用@AfterThrowing注解

    @Around

    1. 环绕通知, 围绕着方法执行
    2. 环绕通知使用@Around注解

    package com.jason.spring.aop.impl;
     
    import java.util.Arrays;
    import java.util.List;
     
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.stereotype.Component;
     
     
    //把这个类声明为一个切面
    //1.需要将该类放入到IOC 容器中
    @Component
    //2.再声明为一个切面
    @Aspect
    public class LoggingAspect {
        
        //声明该方法是一个前置通知:在目标方法开始之前执行 哪些类,哪些方法
        //作用:@before 当调用目标方法,而目标方法与注解声明的方法相匹配的时候,aop框架会自动的为那个方法所在的类生成一个代理对象,在目标方法执行之前,执行注解的方法
        //支持通配符
        //@Before("execution(public int com.jason.spring.aop.impl.ArithmeticCaculatorImpl.*(int, int))")
        @Before("execution(* com.jason.spring.aop.impl.*.*(int, int))")
        public void beforeMethod(JoinPoint joinPoint){
            String methodName = joinPoint.getSignature().getName();
            List<Object> args = Arrays.asList(joinPoint.getArgs());
            System.out.println("The method " + methodName + " begins " + args);
        }
        
        /**
         * @Description:  在方法执行后执行的代码,无论该方法是否出现异常
         * @param joinPoint
         */
        @After("execution(* com.jason.spring.aop.impl.*.*(int, int))")
        public void afterMethod(JoinPoint joinPoint){
            String methodName = joinPoint.getSignature().getName();
            List<Object> args = Arrays.asList(joinPoint.getArgs());
            System.out.println("The method " + methodName + " end " + args);
        }
        
        /**
         * 
         * @Description:  在方法正常结束后执行代码,放回通知是可以访问到方法的返回值
         *
         * @param joinPoint
         */
        @AfterReturning( value="execution(* com.jason.spring.aop.impl.*.*(..))", returning="result")
        public void afterReturning(JoinPoint joinPoint ,Object result){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("The method " + methodName + " end with " + result);
        }
        
        /**
         * 
         * @Description:  在目标方法出现异常时会执行代码,可以访问到异常对象,且,可以指定出现特定异常时执行通知代码
         *
         * @param joinPoint
         * @param ex
         */
        @AfterThrowing(value="execution(* com.jason.spring.aop.impl.*.*(..))",throwing="ex")
        public void afterThrowting(JoinPoint joinPoint, Exception  ex){
            String methodName = joinPoint.getSignature().getName();
            System.out.println("The method " + methodName + " occurs exceptions " + ex);
        }
        
        /**
         * 
         * @Description: 环绕通知需要携带 ProceedingJoinPoint 类型的参数
         *                    环绕通知 类似于  动态代理的全过程
         *                   ProceedingJoinPoint:可以决定是否执行目标方法
         *    环绕通知必须有返回值,返回值即为目标方法的返回值
         *    
         * @param proceedingJoinPoint
         */
        @Around("execution(* com.jason.spring.aop.impl.*.*(..))")
        public Object around(ProceedingJoinPoint proceedingJoinPoint){
            
            Object result = null;
            String methodName = proceedingJoinPoint.getSignature().getName();
            
            //执行目标方法
            try {
                //前置通知
                System.out.println("The method " + methodName + "begin with" + Arrays.asList(proceedingJoinPoint.getArgs()));
                
                result = proceedingJoinPoint.proceed();
                
                //后置通知
                System.out.println("The method " + methodName + "end with" + result);
                
            } catch (Throwable e) {
                //异常通知
                System.out.println("The method occurs exception : " + e);
                throw new RuntimeException();
            }
                //后置通知
                
            System.out.println("The method " + methodName + "end with" + result);
            
            return result;        
        }
    }
    

    切点表达式参考

    展开全文
  • JoinPoint的用法

    2021-02-26 12:08:35
    public void doBefore(JoinPoint jp) throws NoSuchMethodException { visitTime = new Date();//当前时间就是开始访问的时间 clazz = jp.getTarget().getClass(); //具体要访问的类 String methodName = jp....
     	public void doBefore(JoinPoint jp) throws NoSuchMethodException {
            visitTime = new Date();//当前时间就是开始访问的时间
            clazz = jp.getTarget().getClass(); //具体要访问的类
            String methodName = jp.getSignature().getName(); //获取访问的方法的名称
            Object[] args = jp.getArgs();//获取访问的方法的参数
    
    

    实例

    package com.controller;
    
    import com.domain.SysLog;
    import com.service.ISysLogService;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.context.SecurityContext;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import javax.servlet.http.HttpServletRequest;
    import java.lang.reflect.Method;
    import java.util.Date;
    
    @Component
    @Aspect
    public class LogAop {
    
        @Autowired
        private HttpServletRequest request;
    
        @Autowired
        private ISysLogService sysLogService;
    
        private Date visitTime; //开始时间
        private Class clazz; //访问的类
        private Method method;//访问的方法
    
        //前置通知  主要是获取开始时间,执行的类是哪一个,执行的是哪一个方法
        @Before("execution(* com.controller.*.*(..))")
        public void doBefore(JoinPoint jp) throws NoSuchMethodException {
            visitTime = new Date();//当前时间就是开始访问的时间
            clazz = jp.getTarget().getClass(); //具体要访问的类
            String methodName = jp.getSignature().getName(); //获取访问的方法的名称
            Object[] args = jp.getArgs();//获取访问的方法的参数
    
            //获取具体执行的方法的Method对象
            if (args == null || args.length == 0) {
                method = clazz.getMethod(methodName); //只能获取无参数的方法
            } else {
                Class[] classArgs = new Class[args.length];
                for (int i = 0; i < args.length; i++) {
                    classArgs[i] = args[i].getClass();
                }
                clazz.getMethod(methodName, classArgs);
            }
        }
    
        //后置通知
        @After("execution(* com.controller.*.*(..))")
        public void doAfter(JoinPoint jp) throws Exception {
            long time = new Date().getTime() - visitTime.getTime(); //获取访问的时长
    
            String url = "";
            //获取url
            if (clazz != null && method != null && clazz != LogAop.class) {
                //1.获取类上的@RequestMapping("/orders")
                RequestMapping classAnnotation = (RequestMapping) clazz.getAnnotation(RequestMapping.class);
                if (classAnnotation != null) {
                    String[] classValue = classAnnotation.value();
                    //2.获取方法上的@RequestMapping(xxx)
                    RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class);
                    if (methodAnnotation != null) {
                        String[] methodValue = methodAnnotation.value();
                        url = classValue[0] + methodValue[0];
    
                        //获取访问的ip
                        String ip = request.getRemoteAddr();
    
                        //获取当前操作的用户
                        SecurityContext context = SecurityContextHolder.getContext();//从上下文中获了当前登录的用户
                        User user = (User) context.getAuthentication().getPrincipal();
                        String username = user.getUsername();
    
                        //将日志相关信息封装到SysLog对象
                        SysLog sysLog = new SysLog();
                        sysLog.setExecutionTime(time); //执行时长
                        sysLog.setIp(ip);
                        sysLog.setMethod("[类名] " + clazz.getName() + "[方法名] " + method.getName());
                        sysLog.setUrl(url);
                        sysLog.setUsername(username);
                        sysLog.setVisitTime(visitTime);
    
                        //调用Service完成操作
                        sysLogService.save(sysLog);
                    }
                }
            }
    
        }
    }
    
    
    展开全文
  • Proceedingjoinpoint 和JoinPoint的区别: Proceedingjoinpoint 继承了JoinPoint,proceed()这个是aop代理链执行的方法。并扩充实现了proceed()方法,用于继续执行连接点。JoinPoint仅能获取相关参数,无法执行连接点...
  • 簡述下joinpoint在不同情況下的不同:1.在around中可以用,此時可以執行被包裹的代碼,可以根據情況來判斷是否執行被包裹的代碼,以實現控制的作用。publicvoidaround(ProceedingJoinPointjoinpoint){joinpoint....
  • Spring Aop切面参数JoinPoint详解   Spring Aop切面参数JoinPoint详解Spring Aop切面参数JoinPoint详解Spring Aop5种代理通知的写法:1.前置通知2.后置通知3.返回后通知4.异常通知5.环绕通知JoinPoint是什么:...
  • 各位老师大家好,这几天有老师问我joinpoint regression怎么做,为什么看到的joinpoint都是围绕着SEER数据打转转?我针对这个问题参阅了网上的很多文章,在这里首先感谢互联网络提供的知识平台!把我学习的心得分享...
  • 1.JoinPoint @AfterReturning("execution(* com..*.*Mapper.update*(..))|| execution(* com..*.*Mapper.insert*(..))" + " || execution(* com..*.*Mapper.add*(..))") public int afterAddAndUpdate(JoinPoint...
  • AOP JoinPoint

    2021-09-03 15:37:37
    JoinPoint 可获取到切入点的相关信息。 自定义注解 @Action package com.zhujiejoinpoint.demo; import java.lang.annotation.*; @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD...
  • 注意JoinPoint是大写,现在是没有aspectj里的JoinPoint 解决方法: 打开pom.xml文件,把这个删掉,删除完了记得刷新maven 再来看看效果
  • 展开全部this 和 target 的差别在于我们挑选时是按声明类型还是实例类型,按62616964757a686964616fe78988e69d8331333337613832下面链接中提到的代码做个实验来用 static 方法证实有什么差异,我们知道 Java 中静态...
  • AspectJ中的切入点匹配的执行点称作连接的(Join Point),在通知方法中可以声明一个JoinPoint类型的参数。通过JoinPoint可以访问连接点的细节。下面简要介绍JponPoint的方法: 1.java.lang.Object[] getArgs():...
  • public void beforeMethod(JoinPoint joinPoint){ joinPoint.getSignature().getName(); // 获取目标方法名 joinPoint.getSignature().getDeclaringType().getSimpleName(); // 获取目标方法所属类的简单类名 ...
  • springboot注解式AOP通过JoinPoint获取参数 学习笔记 之前开发时,需要获取切点注解的参数值,记录一下 切面注解 : @Aspect – 标识为一个切面供容器读取,作用于类 @Pointcut – (切入点):就是带有通知的连接点 @...
  • JoinPoint joinpoint就是运行时的连接点,根据接口定义我们知道它包裹了要执行的对象,方法,参数等。spring只支持方法类型的连接点,虽然有构造方法连接点的定义,但是未实现,故不支持构造方法。 我们可以看到...
  • spring Aop,关于获取方法参数的泛型类型的代码 ...public void before(JoinPoint joinPoint) { // 获取目标方法(切点方法) MethodSignature signature = (MethodSignature) joinPoint.getSign
  • import org.aspectj.lang.JoinPoint; public class AspectJAop { //实现五个增强通知的方法 public void beforeHandler(JoinPoint jp){ } public void afterHandler(JoinPoint jp,Object ret){ } public ...
  • 4、Joinpoint获取目标方法的信息 4.1、在通知方法运行的时候,拿到目标方法的详细信息 /** * 细节四: * 在通知方法运行的时候,拿到目标方法的详细信息 * 1、只需要为通知方法的参数上写一个参数 * JoinPoint ...
  • 一、joinpoint用法与Before连用(@Before,@AfterReturning,@Around,@AfterThrowing,@After都可以跟joinpoint连用)
  • * @param joinPoint */ public void printExecutionTime(JoinPoint joinPoint) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");//定义时间格式,时间的粒度,控制在毫秒; String now ...
  • Caused by: java.lang.ClassNotFoundException: org.aspectj.lang.JoinPoint 原因 缺少jar包 在pom.xml中添加jar包地址 <dependency> <groupId>org.aspectj</groupId> <artifactId>...
  • NoClassDefFoundError: org/aspectj/lang/JoinPoint 控制台输出: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.context.event....
  • 出现异常:java.lang.ClassNotFoundException: org.aspectj.lang.JoinPoint 缺少execution表达式的jar包 在maven依赖中加入 <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <...
  • Joinpoint(连接点):程序的某个特定位置,比如类开始初始化前,初始化后,方法调用前后,抛出异常前后等。例如:eat方法调用前后 Pointcut(切入点):基于连接点,链接点描述的可以增强的点,如果真的在这个点增强了,...
  • 1.Joinpoint: Signature getSignature():获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息 Object[] getArgs();获取传入目标方法的参数对象 Object getTarget();获取被代理的对象...
  • 任何人可以告诉我,Joinpoint和Proceedingjoinpoint有什么区别?何时在方面的类方法中使用Joinpoint和Proceedingjoinpoint?我在AspectJ类中使用了JoinPoint,@Pointcut("execution(* ...
  • package ...import org.apache.commons.lang3.ArrayUtils;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.Signature;import org.aspectj.lang.reflect.MethodSignature;/*** JoinPo...
  • AOP JoinPoint中的方法

    2021-11-18 19:25:10
    /*获取参数的值数组*/ Object[] args = point.getArgs(); // [1] 参数的值 /*获取目标对象(被加强的对象)*/ Object target = point.getTarget(); /*获取signature 该注解作用在方法上,强转为 Method...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 44,170
精华内容 17,668
关键字:

joinpoint