美文网首页
动态代理

动态代理

作者: holmes000 | 来源:发表于2021-03-25 17:20 被阅读0次

    静态代理:

    就是一种组合方式的,A类组合目标类,A类A方法中引用目标类的a方法;对其进行辅助实现;
    若想调用目标类的a方法,直接可以用A类A方法代理执行;

    1.动态代理:

    JDK动态代理:就是字节码重组过程,主要是生成新的代理类并实现目标类全部方法;

    <font color=Red> 因为是通过实现,被代理类都实现接口 </font>

    JDK动态代理过程
    1.首先通过getInstance获取目标类,然后通过反射获取其全部方法;
    2.Proxy.newProxyInstance通过入参:类的classLoader, 类的接口方法,该JDKDemoPorxy;
    来创建新的代理对象;并且实现全部接口方法;

    Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    
    1. 最终通过invoke 来调用方法;入参:新生成的代理类,调用的目标方法,方法入参 ;
      作用对原有类的接口方法做业务增强,比如before(),after()等方法;
    public Object invoke(Object proxy, Method method, Object[] args)
    

    4.根据上述动态生成java代码,编译新生产的.class文件,重新加载到JVM运行

    //具体使用例子

    //jdk代理类
    public class JDKDemoPorxy implements InvocationHandler {
        private Object target;
        public Object getInstance(Object target) throws Exception {
            this.target = target;
            Class<?> clazz = target.getClass();
            //反射获取目标类方法,并新生成一个代理类,并实现全部方法,其中invoke可以做逻辑切入
            //入参类的classLoader,类的接口,该JDKDemoPorxy
            return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
        }
        //入参:新生成的代理类,调用的目标方法,方法入参
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            before();
            Object obj = method.invoke(this.target, args);
            after();
            return obj;
        }
        private void before() throws Exception {
            System.out.println("before+++");
        }
        private void after() {
            System.out.println("after+++");
        }
    }
    
    public interface Person {
        void getName();
        Long getCreateTime(String param);
    }
    
    //目标类
    public class Customer implements Person {
        @Override
        public void getName() {
            System.out.println("sally");
        }
        @Override
        public Long getCreateTime(String param) {
            System.out.println(param);
            return System.currentTimeMillis();
        }
    }
    //测试使用
    public class JDKProxyTest {
        public static void main(String[] args) throws Exception {
            Person student = (Person) new JDKDemoPorxy().getInstance(new Customer());
            student.getCreateTime("test");
        }
    }
    

    代理重组字节码反编译后生成的文件:

    通过反编译新的代理类文件$Porxy;可以看到 他实现了所有方法,并在static静态块中用反射找到所有方法以m0,m1,m2....来命名方法

    public final class $Proxy0 extends Proxy implements Person{
    ...
      public final void equals(Object obj){
    ...
      return (String)super.h.invoke(this, m2 , new Object[] {
        obj
      })).booleanValue();
    ...
      }
    
      static{
    ...
      m2 = Class.forName("java.lang.Object").getMethod("equals",new Class[]{
      Class.forName("java.lang.Object")
      });
    ...
      }
    }
    

    2.CGlib动态代理

    CGlib动态代理原理:是通过生成子类继承目标类,并覆盖;

    CGlib动态代理过程
    1.首先通过Enhancer,设置目标类,并设置代理为回调,生成代理类继承目标类;

    public Object getInstance(Class<?> clazz) throws Exception {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(clazz);
            enhancer.setCallback(this);
            //生成代理类继承目标类
            return enhancer.create();
        }
    

    2.当调用代理类中方法时,通过MethodInterceptor拦截或说回调到intercept,来触发MethodProxy.invokeSuper;

    @Override
        public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            before();
            //methodProxy invokeSuper触发并生FastClass类,通过FastClass机制
            Object obj = methodProxy.invokeSuper(o,args);
            after();
            return obj;
        }
    
    若缓存中没有,其中为目标类和代理类各生成一个FastClass类,这类会为每个方法分配一个index;
    FastClassInfo fci = fastClassInfo;
    return fci.f2.invoke(fci.i2, obj, args);
    

    获取当前代理类的FastClass类和index,当作入参就可以直接调用方法,省去反射调用;所以比JDK执行效率高;
    FastClass不是和代理一起生成的,而是在第一次执行MethodProxy.invokeSuper生成的,并放在缓存中;

    使用例子

    public class CglibProxyDemo implements MethodInterceptor {
    
        public Object getInstance(Class<?> clazz) throws Exception {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(clazz);
            enhancer.setCallback(this);
            //生成代理类继承目标类
            return enhancer.create();
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            before();
            //methodProxy invokeSuper触发并生FastClass类,通过FastClass机制
            Object obj = methodProxy.invokeSuper(o,args);
            after();
            return obj;
        }
    
    
        private void before() throws Exception {
            System.out.println("before+++");
        }
    
        private void after() {
            System.out.println("after+++");
        }
    }
    public class  CglibProxyTest {
        public static void main(String[] args) throws Exception {
            Person customer = (Person) new CglibProxyDemo().getInstance(Customer.class);
            customer.getName();
        }
    }
    
    

    代理类调用方法时,会MethodInterceptor拦截进入intercept,触发methodProxy.invokeSuper(o,args);
    MethodProxy是很关键的,调用invokeSuper时,为目标类和代理类各生成一个FastClass类,这类会为每个方法分配一个index;
    获取代理类的FastClass根据index,调用方法;

    public class MethodProxy {
    
        private Signature sig1;
    
        private Signature sig2;
    
        private CreateInfo createInfo;
    
        private final Object initLock = new Object();
    
        private volatile FastClassInfo fastClassInfo;
    ···
      private void init() {
            if (fastClassInfo == null) {
                synchronized (initLock) {
                    if (fastClassInfo == null) {
                        CreateInfo ci = createInfo;
    
                        FastClassInfo fci = new FastClassInfo();
                        fci.f1 = helper(ci, ci.c1);
                        fci.f2 = helper(ci, ci.c2);
                        fci.i1 = fci.f1.getIndex(sig1);
                        fci.i2 = fci.f2.getIndex(sig2);
                        fastClassInfo = fci;
                        createInfo = null;
                    }
                }
            }
        }
    。。。
      private static class FastClassInfo {
    
            FastClass f1;
    
            FastClass f2;
    
            int i1;
    
            int i2;
        }
    。。。。
      public Object invokeSuper(Object obj, Object[] args) throws Throwable {
            try {
                            //生成FastClass类 ,若有就从缓存中获取
                init();
                FastClassInfo fci = fastClassInfo;
                            //根据fci.i2的index,去调用方法
                return fci.f2.invoke(fci.i2, obj, args);
            }
            catch (InvocationTargetException e) {
                throw e.getTargetException();
            }
        }
    」
    

    相关文章

      网友评论

          本文标题:动态代理

          本文链接:https://www.haomeiwen.com/subject/qmlrhltx.html