JAVA 动态代理

1 学习动态代理的目的
动态代理技术都是在框架中使用,例如:Struts1、Struts2、Spring和Hibernate中都使用了动态代理技术。如果你不想自己写个框架,那么你基本上是用上不动态代理技术的。学习动态代理技术的目的是为了更好的理解框架内部的原理,也就是说是为了将来学习框架打基础!动态代理技术有点难度!而且明白了动态代理技术可能一时也想不到他适合在什么情况下使用它。这些东西都会在学习框架时渐渐明白。

2 运行时实现指定的接口
想实现某个接口,你需要写一个类,然后在类名字的后面给出“implements”XXX接口。这才是实现某个接口:

复制代码 第1张

复制代码 第2张

上面的代码对我们来说没有什么新鲜感,我们要说的是动态代理技术可以通过一个方法调用就可以生成一个对指定接口的实现类对象。

上面代码中,Proxy类的静态方法newProxyInstance()方法生成了一个对象,这个对象实现了cs数组中指定的接口。没错,返回值mi是MyInterface接口的实现类。你不要问这个类是哪个类,你只需要知道mi是MyInterface接口的实现类就可以了。你现在也不用去管loader和h这两个参数是什么东东,你只需要知道,Proxy类的静态方法newProxyInstance()方法返回的方法是实现了指定接口的实现类对象,甚至你都没有看见实现类的代码。
动态代理就是在运行时生成一个类,这个类会实现你指定的一组接口,而这个类没有.java文件,是在运行时生成的,你也不用去关心它是什么类型的,你只需要知道它实现了哪些接口即可。

3 newProxyInstance()方法的参数
Proxy类的newInstance()方法有三个参数:
ClassLoader loader:它是类加载器类型,你不用去理睬它,你只需要知道怎么可以获得它就可以了:MyInterface.class.getClassLoader()就可以获取到ClassLoader对象,没错,只要你有一个Class对象就可以获取到ClassLoader对象;
Class[] interfaces:指定newProxyInstance()方法返回的对象要实现哪些接口,没错,可以指定多个接口,例如上面例子只我们只指定了一个接口:Class[] cs = {MyInterface.class};
InvocationHandler h:它是最重要的一个参数!它是一个接口!它的名字叫调用处理器!你想一想,上面例子中mi对象是MyInterface接口的实现类对象,那么它一定是可以调用fun1()和fun2()方法了,难道你不想调用一下fun1()和fun2()方法么,它会执行些什么东东呢?其实无论你调用代理对象的什么方法,它都是在调用InvocationHandler的invoke()方法!

JAVA 动态代理|java 动态代理-翰林小院 第3张

复制代码 第4张

复制代码 第5张

InvocationHandler接口只有一个方法,即invoke()方法!它是对代理对象所有方法的唯一实现。也就是说,无论你调用代理对象上的哪个方法,其实都是在调用InvocationHandler的invoke()方法。

想象中的类:

复制代码 第6张

复制代码 第7张

注意,X类是我们用来理解代理对象与InvocationHandler之间的关系的,但它是不存在的类。是我们想象出来的!也就是说,它是用来说明,无论你调用代理对象的哪个方法,最终调用的都是调用处理器的invoke()方法。

4 InvocationHandler的invoke()方法
InvocationHandler的invoke()方法的参数有三个:
Object proxy:代理对象,也就是Proxy.newProxyInstance()方法返回的对象,通常我们用不上它;
Method method:表示当前被调用方法的反射对象,例如mi.fun1(),那么method就是fun1()方法的反射对象;
Object[] args:表示当前被调用方法的参数,当然mi.fun1()这个调用是没有参数的,所以args是一个零长数组。
最后要说的是invoke()方法的返回值为Object类型,它表示当前被调用的方法的返回值,当然mi.fun1()方法是没有返回值的,所以invoke()返回的就必须是null了。

复制代码 第8张

复制代码 第9张

5 动态代理的用途
动态代理的用途与装饰模式很相似,就是为了对某个对象进行增强。所有使用装饰者模式的案例都可以使用动态代理来替换。
下面我们用一个例子来说明动态代理的用途!
我们来写一个Waiter接口,它只有一个serve()方法。MyWaiter是Waiter接口的实现类:

现在我们要对MyWaiter对象进行增强,要让它在服务之前以及服务之后添加礼貌用语,即在服务之前说“您好!”,在服务之后说:“很高兴为您服务!”。

复制代码 第10张

复制代码 第11张

实例(AOP):

JAVA 动态代理|java 动态代理-翰林小院 第12张

复制代码 第13张

复制代码 第14张

JAVA 动态代理|java 动态代理-翰林小院 第15张

复制代码 第16张

复制代码 第17张

JAVA 动态代理|java 动态代理-翰林小院 第18张

复制代码 第19张

复制代码 第20张

JAVA 动态代理|java 动态代理-翰林小院 第21张

JAVA 动态代理|java 动态代理-翰林小院 第22张

JAVA 动态代理|java 动态代理-翰林小院 第23张

复制代码 第24张

复制代码 第25张

©版权声明:本文为【翰林小院】(huhanlin.com)原创文章,转载时请注明出处!

发表评论

电子邮件地址不会被公开。