设为首页 加入收藏

TOP

Java动态代理深入解析(一)
2017-02-08 08:16:41 】 浏览:367
Tags:Java 动态 代理 深入 解析

要想了解Java动态代理,首先要了解什么叫做代理,熟悉设计模式的朋友一定知道在Gof总结的23种设计模式中,有一种叫做代理(Proxy)的对象结构型模式,动态代理中的代理,指的就是这种设计模式。


在我看来所谓的代理模式,和23种设计模式中的“装饰模式”是一个东西。23种设计模式中将它们作为两种模式,网上也有些文章讲这两种模式的异同,从细节来看,确实可以人为地区分这两种模式,但是抽象到一定高度后,我认为这两种模式是完全一样的。因此学会了代理模式,也就同时掌握了装饰模式。


代理模式


代理模式简单来说,就是对一个对象进行包装,包装后生成的对象具有和原对象一样的方法列表,但是每个方法都可以是被包装过的。


静态代理


让我们先来看一段代码:


package common;


public class Test {
? ? static interface Subject{
? ? ? ? void sayHi();
? ? ? ? void sayHello();
? ? }
? ?
? ? static class SubjectImpl implements Subject{


? ? ? ? @Override
? ? ? ? public void sayHi() {
? ? ? ? ? ? System.out.println("hi");
? ? ? ? }


? ? ? ? @Override
? ? ? ? public void sayHello() {
? ? ? ? ? ? System.out.println("hello");
? ? ? ? }
? ? }
? ?
? ? static class SubjectImplProxy implements Subject{
? ? ? ? private Subject target;
? ? ? ?
? ? ? ? public SubjectImplProxy(Subject target) {
? ? ? ? ? ? this.target=target;
? ? ? ? }
? ? ? ?
? ? ? ? @Override
? ? ? ? public void sayHi() {
? ? ? ? ? ? System.out.print("say:");
? ? ? ? ? ? target.sayHi();
? ? ? ? }


? ? ? ? @Override
? ? ? ? public void sayHello() {
? ? ? ? ? ? System.out.print("say:");
? ? ? ? ? ? target.sayHello();
? ? ? ? }
? ? }
? ?
? ? public static void main(String[] args) {
? ? ? ? Subject subject=new SubjectImpl();
? ? ? ? Subject subjectProxy=new SubjectImplProxy(subject);
? ? ? ? subjectProxy.sayHi();
? ? ? ? subjectProxy.sayHello();
? ? }
}
?


这段代码中首先定义了一个Subject接口,接口中有两个方法。


然后定义了SubjectImpl类实现Subject接口并实现其中的两个方法,到这里肯定是没问题的。


现在再定义一个SubjuectImplProxy类,也实现Subject接口。这个SubjectImplProxy类的作用是包装SubjectImpl类的实例,它的内部定义一个变量target来保存一个SubjectImpl的实例。SubjectImplProxy也实现了接口规定的两个方法,并且在它的实现版本中,都调用了SubjectImpl的实现,但是又添加了自己的处理逻辑。


相信这段代码不难理解,它通过对SubjectImpl进行包装,达到了给输出内容添加前缀的功能。这种代理方式叫做静态代理。


动态代理


从上面的演示中我们不难看出静态代理的缺点:我们对SubjectImpl的两个方法,是进行的相同的包装,但是却要在SubjectImplProxy里把相同的包装逻辑写两次,而且以后如果Subject接口再添加新的方法,SubjectImplProxy也必须要添加新的实现,尽管SubjectImplProxy对所有方法的包装可能都是一样的。


下面我把上面例子的静态代理改成动态代理,我们来看一下区别:


package common;


import java.lang.invoke.MethodHandle;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


public class Test {
? ? static interface Subject{
? ? ? ? void sayHi();
? ? ? ? void sayHello();
? ? }
? ?
? ? static class SubjectImpl implements Subject{


? ? ? ? @Override
? ? ? ? public void sayHi() {
? ? ? ? ? ? System.out.println("hi");
? ? ? ? }


? ? ? ? @Override
? ? ? ? public void sayHello() {
? ? ? ? ? ? System.out.println("hello");
? ? ? ? }
? ? }
? ?
? ? static class ProxyInvocationHandler implements InvocationHandler{
? ? ? ? private Subject target;
? ? ? ? public ProxyInvocationHandler(Subject target) {
? ? ? ? ? ? this.target=target;
? ? ? ? }


? ? ? ? @Override
? ? ? ? public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
? ? ? ? ? ? System.out.print("say:");
? ? ? ? ? ? return method.invoke(target, args);
? ? ? ? }
? ? ? ?
? ? }
? ?
? ? public static void main(String[] args) {
? ? ? ? Subject subject=new SubjectImpl();
? ? ? ? Subject subjectProxy=(Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), new ProxyInvocationHandler(subject));
? ? ? ? subjectProxy.sayHi();
? ? ? ? subjectProxy.sayHello();
? ? ? ?
? ? }
}
?


只看main方法的话,只有第二行和之前的静态代理不同,同样是生成一个subjectProxy代理对象,只是生成的代码不同了。静态代理是直接new 一个SubjectImplProxy的实例,而动态代理则调用了java.lang.reflect.Proxy.newProxyInstance()方法,我们来看一下这个方法的源码:


? ? public static Object newProxyInstance(ClassLoader loader,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Class[] interfaces,
? ? ? ? ? ? ? ? ? ?

首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇从JVM的角度来看单例模式 下一篇Java虚拟机字节码执行引擎

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目