代理的三种使用方法总结,带例子

1. 静态代理
2.动态jdk代理
3.spring注解代理

1.静态代理

接口类:

实现类:

 代理类:

 总结:注入对象,代理方法;缺点:接口的所有方法都需要写一遍,有多个方法时重复多;


2.Jdk代理

 代理类:

 用例:

 总结:内部类实现方法实现,优点:可以指定实现特定方法;


3.spring注解代理

代理类:

 


4.Spring Aop5种代理通知的写法:


1.前置通知
@Before("method()")
    public void doBeforeAdvice(JoinPoint joinPoint){
        System.out.println("我是前置通知!!!");
    }

2.后置通知
    @After("method()")
    public void returnAfter(JoinPoint joinPoint){
        System.out.println("我是后置通知!!!");
    }

3.返回后通知
    @AfterReturning(value="method()",returning = "result")
    public void afterReturning(JoinPoint joinPoint,Object result){
        System.out.println("我是返回后通知!!!返回值是:"+result);
    }

4.异常通知
    @AfterThrowing(value = "method()",throwing = "ex")
    public void afterThrowing(JoinPoint joinPoint,Exception ex){
        System.out.println("我是异常通知!!!异常是::"+ex);
    }

5.环绕通知
    @Around(value = "method()")
    public Object aroundLogging(ProceedingJoinPoint joinPoint){
        System.out.println("我是环绕通知");
        joinPoint.proceed();  //调用目标方法
         System.out.println("我是环绕通知");
        return true;
    }


5. JoinPoint是什么:


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

public interface JoinPoint {

    Object getThis();

    Object getTarget();

    Object[] getArgs();

    Signature getSignature();

}

getThis():获取当前对象(代理对象)
getTarget():获取被代理对象
由于AOP代理原理是直接添加字节码文件,不创建新的对象。所以getThis()和getTarget()获取到的是同一个对象。
getArgs():获取被代理方法的参数,返回Object[]。
getSignature():返回Signature 对象。
其他的一些api:

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()));



6. Signature 是什么:


Signature 封装了被代理方法的全部信息(方法命、注解),以及该方法所属类的信息。


可以看到,Signature 是一个父级接口,它有数十个实现类。我们这里模拟一下获取被代理方法的方法对象:


获取到了方法对象之后,我们就可以调用api,获取方法的所有信息,甚至可以调用.invoke()直接调用方法:

ProceedingJoinPoint是什么:
我们注意到,在环绕通知中,参数是ProceedingJoinPoint:

    @Around(value = "method()")
    public Object aroundLogging(ProceedingJoinPoint joinPoint){
        System.out.println("我是环绕通知");
        joinPoint.proceed();  //调用目标方法
         System.out.println("我是环绕通知");
        return true;
    }

我们进去看看ProceedingJoinPoint 的源码:


我们发现ProceedingJoinPoint 是继承了JoinPoint,作为子接口(扩展了两个方法)。
为什么呢?因为ProceedingJoinPoint 是专为环绕通知服务的,既然是环绕通知,那么调用被代理方法的动作就必须我们手动触发了,所以ProceedingJoinPoint 增加了两个新的方法:

proceed():调用被代理方法(无参)
proceed(Object[] var1):调用被代理方法(有参)
 

参考:Spring Aop 5种通知写法及参数JoinPoint详解_joinpoint 添加参数_易柏州Innovation的博客-CSDN博客