码迷,mamicode.com
首页 > 其他好文 > 详细

动态代理与CGLib

时间:2019-12-31 01:24:04      阅读:78      评论:0      收藏:0      [点我收藏+]

标签:java反射机制   oca   生成   ref   ack   加载   代理   method   属性   

一、动态代理是利用Java反射机制实现的

JAVA反射机制:在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

类加载过程中的加载过程会在内存中生成一个代表此Class文件的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。通过这个Class的实例对象,可以知道这个类的所有属性和方法.

JDK中反射包java.lang.reflect则提供了操作这个类的任意方法和属性的设计。java.lang.reflect包中主要实体类Method、Field、Constructor分别对应着类的方法、属性及构造方法,

另外反射包中的Proxy类与InvocationHandler接口是实现了动态代理的超类与接口

java.lang.reflect.Proxy提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

java.lang.reflect.InvocationHandler是代理实例的调用处理程序 实现的接口。

二、动态代理的实现例子

public class DynamicProxyTest {
interface IHello{ void sayHello(); } static class Hello implements IHello{ @Override public void sayHello() { System.out.println("hello world"); } } static class DynamicProxy implements InvocationHandler{ Object target; Object bind(Object target){ this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("welcome"); return method.invoke(target,args); } } public static void main(String[] args){ IHello target = new Hello(); System.out.println(target.getClass().getClassLoader()); System.out.println(Arrays.toString(target.getClass().getInterfaces())); System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");//在对应package下生成代理类$Proxy0.class IHello hello = (IHello) new DynamicProxy().bind(target); hello.sayHello(); } }
其中Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this)这行代码生成的代理类$Proxy0.class,如下
package com.sun.proxy;

import com.app.proxy.IHello;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements IHello {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void sayHello() throws  {
        try {
            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);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m3 = Class.forName("com.app.proxy.IHello").getMethod("sayHello");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}
可以看出生成的代理类
继承了Proxy,实现了target.getClass().getInterfaces()--IHello,组合了this--构造方法中super(InvocationHander)
不仅实现了被代理类接口的方法sayHello,另外重写了toString,hashCode,equals方法,但格式都是一样的
super.h.invoke(this,mx,new Object[]{varx});//super.h.invoke即invocationHandler接口的实现类DynamicProxy.invoke(),
这样导致代理类的hashCode,toString与被代理类的hashCode,toString
一样,但是实际类型是不同的。下面是一些验证
public static void main(String[] args) {
        IHello target = new Hello();
        IHello hello = (IHello) new DynamicProxy().bind(target);
        System.out.println("target.toString:"+target.toString());//target.toString:com.app.proxy.Hello@eed1f14
        System.out.println("target.hashCode:"+target.hashCode());//target.hashCode:250421012
        System.out.println("proxy.toString:"+hello.toString());//proxy.toString:com.app.proxy.Hello@eed1f14
        System.out.println("proxy.hashCode:"+hello.hashCode());//proxy.hashCode:250421012
        System.out.println("target == proxy:"+(target == hello));//target == proxy:false
        hello.sayHello();
}

 



动态代理与CGLib

标签:java反射机制   oca   生成   ref   ack   加载   代理   method   属性   

原文地址:https://www.cnblogs.com/wqff-biubiu/p/12122158.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!