zoukankan      html  css  js  c++  java
  • java代理浅述

    代理

    代理主要可以分为:

    • 静态代理
    • JDK自带的动态代理
    • Cglib

    静态代理

    静态代理比较简单,简单来说就是不想直接调用被代理类,通过代理类来实现功能。如下就是使用了静态代理

    定义接口

    public interface BookFace {
        public void addBook();
        public void addapple();
    }
    
    public class BookFaceImp implements BookFace {
        @Override
        public void addBook()
        {
            System.out.println("增加图书方法");
        }
        @Override
        public void  addapple()
        {
            System.out.println("增加苹果");
        }
    
    }
    
    public class BookFaceStatic implements BookFace{
        private BookFace target;
    
        public  BookFaceStatic(BookFace target)
        {
            this.target=target;
    
        }
        @Override
        public void addBook() {
            System.out.println("美术图书");
            target.addBook();
    
        }
    
        @Override
        public void addapple() {
            System.out.println("红苹果");
            target.addapple();
    
        }
    }
    

    编写单测:

    @Test
        public void test3()
        {
            BookFaceStatic faceStatic=new BookFaceStatic(new BookFaceImp());
            faceStatic.addBook();
            faceStatic.addapple();
    
     }
    

    输出结果:

    上述就是一个简单的静态代理,就是讲需要的被代理类作为参数传入待代理类中。

    JDK自带的动态代理

    java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

    JDK动态代理只能对实现了接口的类生成代理,而不能针对类。

    延续使用上述的接口和接口实现类,核心代码如下:

    public class BookFaceProcyJDK  implements InvocationHandler {
        private Object target;
    
        public  Object getProcy(Object target)
        {
            //获取到是哪个类需要代理
            this.target=target;
            //getInterfaces()获取代理类的接口
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
        }
        //重写invoke方法,InvocationHandler中自动会执行
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("批量执行1");
            Object result=method.invoke(target,args);
            System.out.println("批量执行2");
            return result;
        }
    }
    

    编写单测:

       @Test
        public void test1()
        {
            BookFaceImp bookFaceImp=new BookFaceImp();
            BookFaceProcyJDK bookFaceProcy=new BookFaceProcyJDK();
            BookFace bookFace= (BookFace)bookFaceProcy.getProcy(bookFaceImp);
            bookFace.addBook();
            bookFace.addapple();
        }
    

    输出结果:

    采坑:
    为什么BookFace bookFace= (BookFaceImp)bookFaceProcy.getProcy(bookFaceImp);
    不能这样写???

    解释:因为代理时相当于新建了一个BookFaceImp1,要么写成(BookFaceImp1)bookFaceProcy.bind(bookFaceImp)或者使用它的父类BookFace,因为不知道到底生成了一个什么名字的BookFaceImp,所以得使用它的父类BookFace。

    (代理生成的BookFaceImp1和BookFaceImp是统一层级的)

    Cglib

    cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

    CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法。

    延续使用上述的接口和接口实现类,核心代码如下:

      public class BookFaceProcyCglib implements MethodInterceptor {
    
        private Object target;
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    
            System.out.println("监听开始");
            Object result=method.invoke(target,args);
            System.out.println("监听结束");
            return result;
        }
        public Object getProcy(Object target)
        {
            this.target=target;
            Enhancer enhancer=new Enhancer();
            //设置父类,因为cglib是设置子类
            enhancer.setSuperclass(target.getClass());
            //设置回调
            enhancer.setCallback(this);
            return  enhancer.create();
        }
    }
    

    单测:

       @Test
        public void test2()
        {
            BookFaceImp bookFaceImp=new BookFaceImp();
            BookFaceProcyCglib bookFaceProcy=new BookFaceProcyCglib();
            BookFace bookFace= (BookFace)bookFaceProcy.getProcy(bookFaceImp);
            bookFace.addBook();
            bookFace.addapple();
        }
    

    运行结果:

    Cglib与jdk自带的动态代理不同是生成的bookFaceImp1的父类是bookFaceImp


    所以 BookFace bookFace= (BookFace)bookFaceProcy.getProcy(bookFaceImp)也可以改成 BookFace bookFace= (BookFaceImp)bookFaceProcy.getProcy(bookFaceImp),效果一致

  • 相关阅读:
    POJ 1016 不断压缩字符串判断三种结果
    递归的运行机制简单理解
    模拟链表
    输入两个字符串,不用系统提供的函数strcat,自定义函数将两个字符串连接起来。
    信号量多线程同步
    windows 多线程同步技术
    qsort和sort的区别(转)
    大数阶乘位数
    字符串数组qsort排序
    Safecracker
  • 原文地址:https://www.cnblogs.com/lixuan1998/p/11266687.html
Copyright © 2011-2022 走看看