zoukankan      html  css  js  c++  java
  • 动态代理:jdk动态代理和cglib动态代理

    /**
     * 动态代理类:先参考代理模式随笔,了解代理模式的概念,分为jdk动态代理和cglib,jdk动态代理是通过实现接口的方式创建代理类的,cglib是通过继承类的方式实现的代理类的
     * jdk动态代理需要用到jdk自带的一个类Proxy来生成代理类,还需要一个提供执行方法的执行接口InvocationHandler.代理类通过底层反编译后可以看到是调用
     * InvocationHandler的invoke方法实现
     *
     *
     */
    //父接口
    public interface IRun {
        void run();
    }
    //被代理类
    public class Runner implements IRun {
        @Override
        public void run() {
            System.out.println("运动员开跑...............");
        }
    }
    //实现一个执行类,代理类底层是通过这个类来执行被代理类的方法
    
    public class MyInvocationHandler implements InvocationHandler {
        private IRun run; //被代理类
    
        public MyInvocationHandler(IRun run) {
            this.run = run;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("执行之前进行检查");
            method.invoke(run,args); //反射执行被代理类的方法
            System.out.println("执行之后.....");
            return null;
        }
    
        //通过Proxy获取获取代理类
        public IRun getProxy(){
    
            return (IRun) Proxy.newProxyInstance(run.getClass().getClassLoader(),run.getClass().getInterfaces(),this);
        }
    
    
        //Proxy.newProxyInstance()底层是调用ProxyGenerator.generateProxyClass来生成字节码的,这里模拟实现,将代理生成的字节码文件输出来,然后反编译
        public static void createProxyClassFile(){//生成字节码对象
            String name = "ProxyRun.class";
            byte[] data = ProxyGenerator.generateProxyClass(name,new Class[]{IRun.class});
            FileOutputStream out =null;
            try {
                out = new FileOutputStream( System.getProperty("user.dir") + File.separator + name);
                out.write(data);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(null!=out) try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public class Test {
        public static void main(String[] args) {
            Runner runner = new Runner();//被代理类
            MyInvocationHandler handler = new MyInvocationHandler(runner);//执行处理的类
            IRun proxy = handler.getProxy();//获取代理类
            proxy.run();//代理类执行方法
            //输出代理类的字节码文件,通过反射可以看到实现原理
            MyInvocationHandler.createProxyClassFile();
        }
    
    }
    //对代理类字节码文件反编译,可以看到是通过实现IRun接口
    public final class $proxy0 class extends Proxy implements IRun {
        private static Method m1;
        private static Method m3;
        private static Method m2;
        private static Method m0;
    
        public class(InvocationHandler var1) throws  {
            super(var1);
        }
    
        public final boolean equals(Object var1) throws  {
            try {
                return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
            } catch (RuntimeException | Error var3) {
                throw var3;
            } catch (Throwable var4) {
                throw new UndeclaredThrowableException(var4);
            }
        }
    
        public final void run() throws  {
            try {
                //可见底层是调用InvocationHandler的invoke方法
                super.h.invoke(this, m3, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
    
        public final String toString() throws  {
            try {
                return (String)super.h.invoke(this, m2, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
    
        public final int hashCode() throws  {
            try {
                return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
    
        static {
            try {
                m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
                m3 = Class.forName("builder.IRun").getMethod("run", new Class[0]); //run方法
                m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
                m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            } catch (NoSuchMethodException var2) {
                throw new NoSuchMethodError(var2.getMessage());
            } catch (ClassNotFoundException var3) {
                throw new NoClassDefFoundError(var3.getMessage());
            }
        }
    }
    //cglib实现动态代理,该方式因为不是jdk自带的,所以需要引入相应的依赖包(spring框架自带相应的依赖包了),代理类需要实现MethodInterceptor相当于jdk动态代理的InvocationHandler,
    //覆写intercept相当于InvocationHandler的invoke方法,生成代理类是通过Enhancer类来生成的
    public class Dog {
    
        public void sout(){
            System.out.println("汪汪");
        }
    }
    public class DogProxy implements MethodInterceptor {
    
    
        private Dog target;
        public DogProxy(Dog target) {
            this.target = target;
        }
        public Object bind(){
            Enhancer enhancer = new Enhancer();//创建加强器,用来创建动态代理类
            enhancer.setSuperclass(target.getClass());//为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
            enhancer.setCallback(this); //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
            return enhancer.create();
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("开始");
            method.invokeSuper(o,objects);
            System.out.println("结束");
            return null;
        }
    }
  • 相关阅读:
    eclipse工具
    Tag
    JSP模版
    Eclipse断点调试
    JavaBean
    验证码设计
    在IE中提示404错误
    序列化与反序列化
    文件编码问题
    强类型,弱类型和推断类型
  • 原文地址:https://www.cnblogs.com/yangxiaohui227/p/10913593.html
Copyright © 2011-2022 走看看