您的位置:首页 > 编程语言 > Java开发

java动态代理实现

2016-03-15 10:30 381 查看
为什么要用动态代理

动态代理的实现

为什么要用动态代理

我们开发软件的过程中,通常会有各种各样的相同代码重复出现。遇到这种情况,一般会有三种做法,最不可取的是一路“复制”,“粘贴”到底,写起来挺爽,要是去维护,简直是噩梦;稍有经验的都会将这些重复的代码独立出来,在别的地方直接引用即可。但这样也有一个问题,程序中必须要硬编码去直接调用独立出来的方法,有没有一种即可以执行独立方法,又不用硬编码调用的优雅方法,这个时候就可以考虑动态代理了。

动态代理的实现

要实现动态代理,必须先要了解两个类Proxy和InvocationHandler。

Proxy是所有动态代理类的父类,包含了用于创建动态代理类和代理对象的静态方法。用的较多的的getProxyClass()和newProxyInstance()这两个方法,从名字上估计你已经看出来了,前者是用来创建一个动态代理类;后者则是创建一个动态代理对象。

不管用哪一种方法,有一点是肯定的,每一个代理对象都必须有一个InvocationHandler类与之关联。这个InvocationHandler是个很奇妙的类,有了它之后,就可以接管动态代理对象里的方法。也就是说当执行动态代理对象里的方法时,实际上执行的是InvocationHandler对象的invoke方法。

说到这里,应该明白动态代理所需要的几样东西了吧:

(1)接口。jdk动态代理只能为接口创建;

(2)有接口当然得有接口的各种实现类,记做A。(有同学可能要问,为什么需要各种实现类呢?那是因为如果直接为接口创建动态代理对象,那代理对象所有的执行方法是不是都一样?可不就失去了它的意义);

(3)通用代码块,就是前面提到的独立代码块,记做B。用各种A来调用B,是不是就模拟了前面提到的问题?;

(4)重要的InvocationHandler类。执行代理对象的所有方法都会转换为InvocationHandler的invoke方法。所以B方法通常也放在invoke里面实现。

下面我们用个简单的例子来实现一下:

首先定义一个Person接口。

public interface Person {
void eat();
void sleep();
}


接着实现这个接口。

public class ImplementPerson implements Person {

@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("=-=-=吃了吃了=-=-=");
}

@Override
public void sleep() {
// TODO Auto-generated method stub
System.out.println("=-=-=睡了睡了=-=-=");
}
}


定义公共代码块。

public class PersonUtils {
public void commonMethodOne() {
System.out.println("=-=-=公共方法1");
}

public void commonMethodTwo() {
System.out.println("=-=-=公共方法2");
}
}


定义自己的InvocationHandler,动态代理的关键实现。

public class MyInvokationHandler implements InvocationHandler {

private Object target;

public void setTarget(Object target) {
this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
PersonUtils personUtils = new PersonUtils();
// 执行PersonUtils的commonMethodOne方法
personUtils.commonMethodOne();
// 以target为主调,执行method方法;
Object result = method.invoke(target, args);
// 执行PersonUtils的commonMethodTwo方法
personUtils.commonMethodTwo();
return result;
}
}


创建一个代理工厂,为指定的target生成动态代理实例。

public class MyProxyFactory {
public static Object getProxy(Object target) {
MyInvokationHandler myInvokationHandler = new MyInvokationHandler();
// 为myInvokationHandler设置target对象
myInvokationHandler.setTarget(target);
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), myInvokationHandler);
}
}


最后就是个测试类了。

public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
// 创建一个ImplementPerson对象,作为主调target
Person target = new ImplementPerson();
// 创建一个动态代理对象person
Person person = (Person) MyProxyFactory.getProxy(target);
person.sleep();
person.eat();
}

}


运行的效果,贴出来:

=-=-=公共方法1
=-=-=睡了睡了=-=-=
=-=-=公共方法2
=-=-=公共方法1
=-=-=吃了吃了=-=-=
=-=-=公共方法2


有了这些实现,不难看出动态代理可以很灵活地实现解耦。普通的编程中,用的比较少,但在编写框架或者底层代码时,动态代理就可大显身手了。

AOP编程中把这类动态代理叫做AOP代理,即可在执行目标方法之前,之后加入一些通用处理。至于更深层次的AOP编程,水平有限,请自行探讨。

附上代码链接,可免去粘贴之苦。

http://download.csdn.net/detail/luochoudan/9462093

欢迎留言拍砖。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: