第⼆⼗四章 Spring AOP⾥⾯的代理知识你知道多少

1集 你知道动态代理和静态代理吗

简介:讲解静态代理和动态代理 

  • 什么是代理 
    • 为某⼀个对象创建⼀个代理对象,程序不直接⽤原本的对象,⽽是由创建的代理对象来控制对原对象,通过代理类这中间⼀层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间
    • A ->B-> C
  •  什么是静态代理
    • 由程序创建或特定⼯具⾃动⽣成源代码,在程序运⾏前,代理类的.class⽂件就已经存在
  •  什么是动态代理
    • 在程序运⾏时,运⽤反射机制动态创建⽽成,⽆需⼿动编写代码
      • JDK动态代理
      • CGLIB 动态代理

2集 代理模式实战之静态代理讲解 

简介:讲解静态代理优缺点和实操
  • 什么是静态代理
    • 由程序创建或特定⼯具⾃动⽣成源代码,在程序运⾏前,代理类的.class⽂件就已经存在
    • 通过将⽬标类与代理类实现同⼀个接⼝,让代理类持有真实类对象,然后在代理类⽅法中调⽤真实类⽅法,在调⽤真实类⽅法的前后添加我们所需要的功能扩展代码来达到增强的⽬的
    • A -> B -> C
  • 优点 
    • 代理使客户端不需要知道实现类是什么,怎么做的,⽽客户端只需知道代理即可
    • ⽅便增加功能,拓展业务逻辑
  • 缺点 
    • 代理类中出现⼤量冗余的代码,⾮常不利于扩展和维护
    • 如果接⼝增加⼀个⽅法,除了所有实现类需要实现这个⽅法外,所有代理类也需要实现此⽅法。增加了代码维护的复杂度

PayService接口:(被代理类)

public interface PayService {

    String callback(String OutTradeNo);
    //根据用户和视频id进行存储
    int save(int userId ,int VideoId);
}

PayServiceImpl实现类:(被代理类实现类)

ublic class PayServiceImpl implements PayService {
    public String callback(String OutTradeNo) {
        return OutTradeNo;
    }

    public int save(int userId, int VideoId) {
        //假设执行成功
        return 0;
    }
}

静态代理实现接口:

//静态实现类
public class StaticPayServiceImpl implements PayService {
    private PayService payService;
    public StaticPayServiceImpl(PayService payService){
        this.payService = payService;
    }
    public String callback(String OutTradeNo) {
        System.out.println("StaticPayServiceImpl callback begin");
       String result =  payService.callback(OutTradeNo);
        System.out.println(result);
        System.out.println("StaticPayServiceImpl callback end");
        return result;
    }

    public int save(int userId, int VideoId) {
        System.out.println("StaticPayServiceImpl save begin");
        int save = payService.save(userId, VideoId);
        System.out.println(save);
        System.out.println("StaticPayServiceImpl save end");
        return save;
    }
}

测试方法:

  @Test
    public void Test(){

        StaticPayServiceImpl staticPayService = new StaticPayServiceImpl(new PayServiceImpl());
        staticPayService.callback("执行Callback");

        staticPayService.save(11,22);
    }

运行结果:

3AOP的实现策略之JDK动态代理 

简介:讲解AOP常⻅的实现的策略JDK动态代理 

  • 什么是动态代理 
    • 在程序运⾏时,运⽤反射机制动态创建⽽成,⽆需⼿动编写代码
    • JDK 动态代理与静态代理⼀样,⽬标类需要实现⼀个代理接⼝ , 再通过代理对象调⽤⽬标⽅法
  •  实操:

被代理类 - 目标类:

public interface PayService {

    String callback(String OutTradeNo);
    //根据用户和视频id进行存储
    int save(int userId ,int VideoId);
}
public class PayServiceImpl implements PayService {
    public String callback(String OutTradeNo) {
        return OutTradeNo;
    }

    public int save(int userId, int VideoId) {
        //假设执行成功
        return 0;
    }
}

动态代理类:核心代码!

public class jdkProxy implements InvocationHandler {
    //目标类也就是被代理类
    private Object target;


    //获取代理类对象
    public Object newProxyInstace(Object target){
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),
                this);
    }

    //    使用jdk实现动态代理需要实现InvocationHandler并重写invoke方法
    public Object invoke(Object proxy, Method method, Object[] args)  {
        Object result = null;
        try{
            //增强处理
            System.out.println("通过动态代理调用"+method.getName()+"打印日志Begin");
            //执行目标类的方法
            result = method.invoke(target, args);
            System.out.println(result);
            System.out.println("通过动态代理调用"+method.getName()+"打印日志end");
        }catch (Exception e){

        }

        return result;
    }


}

测试类:

public class DongTaiProxy {
    public static void main(String[] args) {
        //测试动态代理
        //1.创建被代理类实现类 -目标类
        PayService payService = new PayServiceImpl();

        //2.创建jdkProxy对象
        jdkProxy jdkProxy = new jdkProxy();

        //3.使用jdkProxy对象创建动态代理 注意动态代理只能代理接口类型
        PayService DongTaiProxyPayService = (PayService)jdkProxy.newProxyInstace(payService);
        String result = DongTaiProxyPayService.callback("使用动态代理执行callback");


    }
}

运行结果:

4AOP的实现策略之CGLib动态代理 

简介:讲解AOP常⻅的实现的策略JDK动态代理 

  • 什么是动态代理 
    • 在程序运⾏时,运⽤反射机制动态创建⽽成,⽆需⼿动编写代码
    • CgLib 动态代理的原理是对指定的业务类⽣成⼀个⼦类,并覆盖其中的业务⽅法来实现代理
  • 代码实现
被代理类与第三章一样
CGLib代理类实现:核心代码! 需要实现MethodInterceptor 
//基于Spring AOP包实现CGLib动态代理,需要导入Spring-core包
public class CGLibProxy implements MethodInterceptor {
    private Object target;
    public Object newProxyInstance(Object target){
        this.target = target;
        Enhancer enhancer = new Enhancer();

        //设置代理类的父类 (目标类)
        enhancer.setSuperclass(this.target.getClass());

        //设置回调函数,使用这个方法之后可以执行目标类的任何方法
        enhancer.setCallback(this);

        //创建子对象 (代理类对象)
        return enhancer.create();
    }
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
      Object result= null;
        try{
            //增强处理
            System.out.println("通过CGLib动态代理调用"+method.getName()+"打印日志Begin");
            //使用methodProxy执行父类的目标类方法
            result = methodProxy.invokeSuper(o,args);
            System.out.println(result);
            System.out.println("通过CGLib动态代理调用"+method.getName()+"打印日志end");
        }catch (Exception e){

        }
        return result;
    }

}

测试类:

   @Test
    public void CGLibTest(){
        //测试动态代理
        //1.创建被代理类实现类 -目标类
        PayService payService = new PayServiceImpl();

        //2.创建cgLibProxy对象
        CGLibProxy cgLibProxy = new CGLibProxy();

        //3.使用cgLibProxy对象创建动态代理 注意动态代理只能代理接口类型
        PayService DongTaiProxyPayService = (PayService) cgLibProxy.newProxyInstance(payService);
        String result = DongTaiProxyPayService.callback("使用动态代理执行callback");
    }

运行结果:

5CGLib动态代理和JDK动态代理总结 

简介:总结CGlibJDk动态代理 

  • 动态代理与静态代理相⽐较,最⼤的好处是接⼝中声明的所有⽅法都被转移到调⽤处理器⼀个集中的⽅法中处理,解耦和易维护

 两种动态代理的区别:

  • JDK动态代理:要求⽬标对象实现⼀个接⼝,但是有时候⽬标对象只是⼀个单独的对象,并没有实现任何的接⼝,这个时候就可以⽤CGLib动态代理
  • CGLib动态代理,它是在内存中构建⼀个⼦类对象从⽽实现对⽬标对象功能的扩展
  • JDK 动态代理是⾃带的, CGlib 需要引⼊第三⽅包
  • CGLib 动态代理基于继承来实现代理,所以⽆法对 fifinal 类、 private ⽅法和 static ⽅法实现代理

Spring AOP中的代理使⽤的默认策略:

  • 如果⽬标对象实现了接⼝,则默认采⽤JDK动态代理
  • 如果⽬标对象没有实现接⼝,则采⽤ CgLib 进⾏动态代理
  • 如果⽬标对象实现了接扣,程序⾥⾯依旧可以指定使⽤ CGlib 动态代理

猜你喜欢

转载自blog.csdn.net/LiuJia20010827/article/details/126187297