java动态代理笔记

        一直没有养成写博客的习惯,后来觉得还是有必要的。一来可以总结和记录,二来我觉得学习知识是一个转换的过程,最终变成自己的理解,能深入浅出的表述出来。这也是我需要不断锻炼的地方。

代理是一种设计模式有很多种:

        1、静态代理 (类似于装饰者模式)。

        2、jdk代理 (利用java的发射技术)。

        3、cglib代理。

前两种是面向接口的,必须实现一个或多个接口。cglib可以对单个类实现代理。这里我主要讲的是jdk动态代理。jdk的动态代理主要用到了两个东西Proxy,InvocationHandler。我把图贴出来先混个脸熟。

Proxy:里面的newProxyInstance()的静态方法就是用来程序运行时生成代理类的。



InvocationHandler:它是一个接口{从代理类对象方法到被代理类(目标类)方法的调用就是通过这个接口}里面只有一个invoke方法,需要我们自己实现。

下面来走一下动态代理的过程,体会一下。

这是目录结构:


一、首先我们需要一个接口

//动态代理是面向接口的
public interface MyProxy {

	public void sayHello();

}

二、对接口进行实现

//这个就是被代理类或者叫目标类
public class MyProxyImpl implements MyProxy {

	public void sayHello() {
		System.out.println("hello");
	}

}

三、对InvocationHandler调用处理器进行实现

//调用处理器
public class MyInvokeHandler implements InvocationHandler {
	
	//目标类的对象
	MyProxy mpi;
	//构造中对目标类的对象进行初始化
	public MyInvokeHandler(MyProxy mpi){
		this.mpi = mpi;
	}
	/**
	 * 
	 * proxy:生成的代理类对象--这个参数貌似没用到,目前我还不知道有什么用处
	 * method:目标类方法的对象
	 * args:目标类方法参数
	 */
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("调用目标类对象方法之前....");
		
		//这里就是利用了java的反射技术来进行
		Object obj = method.invoke(mpi, args);
		
		System.out.println("调用目标类对象方法之后....");
		return obj;
	}
}

四:用户端:生成代理对象并且进行方法调用

//用户端:生成代理对象并且进行方法调用
public class ProxyTest {

	public static void main(String[] args) {
		//创建需要被代理的目标类对象
		MyProxy myProxy = new MyProxyImpl();
		//得到目标类对象的类信息
		Class<?> clazz = myProxy.getClass();
		//创建调用处理器,把目标类对象传入
		InvocationHandler ih = new MyInvokeHandler(myProxy);
		/**
		 * 生成代理类
		 * 参数1:类加载器
		 * 参数2:目标类对象实现的接口数组
		 * 参数3:调用处理器
		 */
		MyProxy proxy = (MyProxy) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), ih);
		//调用代理类对象方法。
		proxy.sayHello();
	}
}

五:输出结果


从输出结果可以看到,由于对目标类MyProxyImpl进行了代理,在打印hello前后各打印了一句话 结果预期。

但是在刚开始的时候有两个问题不解:

1、就是MyInvokeHandler对象是怎么调用?

2、这里我一直感觉怪怪的,从代理类对象的sayHello()到目标类对象的sayHello()是怎么做到的?

--带着这两个问题只要看看我们生成的代理类就茅塞顿开了,下面是生成的代理类。

/**
  * 生成的代理类
  * 1、继承了Proxy。
  * 2、跟目标类一样,也实现了MyProxy接口。
  *
  */
 public final class $Proxy0 extends Proxy implements MyProxy {  
    private static Method m1;  
    private static Method m0;  
    private static Method m3;  
    private static Method m2;  
  
    static {  
        try {  
            m1 = Class.forName("java.lang.Object").getMethod("equals",  
                    new Class[] { Class.forName("java.lang.Object") });  
  
            m0 = Class.forName("java.lang.Object").getMethod("hashCode",  
                    new Class[0]);  
            //通过反射得到目标类sayHello方法对象
            m3 = Class.forName("***.MyProxyImpl").getMethod("sayHello",  
                    new Class[0]);  
  
            m2 = Class.forName("java.lang.Object").getMethod("toString",  
                    new Class[0]);  
  
        } catch (NoSuchMethodException nosuchmethodexception) {  
            throw new NoSuchMethodError(nosuchmethodexception.getMessage());  
        } catch (ClassNotFoundException classnotfoundexception) {  
            throw new NoClassDefFoundError(classnotfoundexception.getMessage());  
        }  
    } //static  
  
    //构造中调用了父类构造并对父类对象中InvocationHandler属性赋值
    public $Proxy0(InvocationHandler invocationhandler) {  
        super(invocationhandler);  
    }  
    
    //生成的代理类方法
    public final void sayHello() {  
        try {  
            //这里调用父类的InvocationHandler对象的invoke方法
            super.h.invoke(this, m3, null);  
            return;  
        } catch (Error e) {  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
  
    @Override  
    public final boolean equals(Object obj) {  
        try {  
            return ((Boolean) super.h.invoke(this, m1, new Object[] { obj })) .booleanValue();  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
  
    @Override  
    public final int hashCode() {  
        try {  
            return ((Integer) super.h.invoke(this, m0, null)).intValue();  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
  
    @Override  
    public final String toString() {  
        try {  
            return (String) super.h.invoke(this, m2, null);  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
}

这个生成的代理类完全解释我上面的疑惑。

通过调用newProxyInstance()系统会生成$Proxy0类,并且继承Proxy和实现MyProxy。再通过$Proxy0类的构造方法调用父类构造对InvocationHandler属性赋值,这样就可以在$Proxy0类的sayHello方法中调用InvocationHandler对象的invoke()。

生成的$Proxy0类中也对equals、hashCode、toString进行了重写。

大概过程就是这样,可能有些地方讲的不清楚,自己还多回头多看看。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值