JDK动态代理实现原理

昨天下午终于签好了合同。今天下午午觉醒来,便开始了JDK动态代理模拟原理的学习和研究。
首先,我们应该明白何为代理,所谓代理,按照我的理解,用户只需要知道接口中的方法名,不需要了解方法中的具体实现,就可以进行远程访问。
在应用上可以用在考试系统中,一个服务器,多个考试机调用服务器上面的方法,以及其他的一些web应用。同时,很多开源框架上也用到了反射,如spring对封装的数据库事务控制,对业务bean的创建。
再者,对于代理,分为两种,一种是静态代理,一种为动态代理。无论静态代理还是动态代理,一下几个模块:1.接口类 2. 真实实现类 3. 代理类(动态代理和静态代理有区别) 4. 代理工厂类。 对于静态代理,代理类中要有接口类中全部方法的实现,这样一来,如果项目后期工程中在接口中增加方法时,则在代理中同样要对该方法进行增加调用,这样一来维护起来麻烦,对于动态代理,则不存在此问题,因为在动态代理的类中,只需要实现InvocationHandler中的invoke方法即可,该方法可以调用接口中的所有方法。
动态代理的实现主要还是借助JDK中的反射机制,主要使用到了java.lang.reflect包中的InvocationHandler接口、Proxy类,java.lang.ClassLoader类。
InvocationHandler接口是代理程序实现逻辑的接口,Proxy创建动态代理类使用。
Proxy类,提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类 ,这里主要用到了newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法,需要说明下ClassLoader指的是代理类的处理机(InvocationHander)的ClassLoader,接口指的是实际对象实现的接口,InvocationHander就是InvocationHander,至于其他的静态方法,你可以自己查API(备注:我用的JDK是1.6),生成的代理类就声称实现了对应的接口并实现了对应的方法。
ClassLoader类:负责加载类的对象,数组类(Array)除外。
下面开始进行动态代理的springAOP控制原理的演示:
首先进行结构说明:
1.接口(必须要有,JDK创建代理对象需要用到)
2.接口实现类
3.代理类(AOP,事务控制,日志记录等)
4.代理工厂
5.测试类
1.接口:
Subject(此处是参考iteye别处的代码,不是原创)
/**
* 顶层接口
*
* @author iteye 2013-07-13
*/
public interface Subject {
/**
* 执行任务1
* @param taskName1 任务名
*/
public abstract void doTask1(String taskName1);

/**
* 执行任务2
* @param taskName2 任务名
*/
public abstract void doTask2(String taskName2);

/**
* 执行任务3
* @param taskName3 任务名
*/
public abstract void doTask3(String taskName3);
}
2.接口实现类

/**
* 动态代理实现类
*
* @author XiaoYun 2013-07-13
*/
public class RealSubject implements Subject {

@Override
public void doTask1(String taskName1) {
System.out.println(taskName1 + "开始执行!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(taskName1 + "执行完毕!");
}

@Override
public void doTask2(String taskName2) {
System.out.println(taskName2 + "开始执行!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(taskName2 + "执行完毕!");
}

@Override
public void doTask3(String taskName3) {
System.out.println(taskName3 + "开始执行!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(taskName3 + "执行完毕!");
}

}
3.动态代理类
/**
* 代理实例的调用处理程序
*
* @author XiaoYun 2013-07-13
*/
public class ProxySubject implements InvocationHandler{

private Object delegate;

public ProxySubject(Object delegate) {
this.delegate = delegate;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//此处可以进行日志记录或者事务操作
//Spring的AOP原理就是如此
method.invoke(delegate, args);
//此处可以进事务处理操作(数据库回滚可以放到异常中进行)
System.out.println(args[0] + "已执行!");
return null;
}

}
说明:如果为静态代理类:则invoke方法需要去掉,然后根据接口中的方法加上对应的方法,并在该方法中加上方法调用。说到这里可能可能大家也都晕了,还是把代码写出来吧,对应的应该是这样子:

/**
* 静态代理类,要实现接口类(此处参考了iteye的部分代码)
* @author iteye 2013-07-13
*/
public class ProxySubject implements Subject {

private Subject delegate;

public ProxySubject(Subject delegate) {
this.delegate = delegate;
}
/**
* 代理方法
*/
@Override
public void doTask1(String taskName) {
this.delegate.doTask(taskName);
}
@Override
public void doTask2(String taskName) {
this.delegate.doTask(taskName);
}
@Override
public void doTask2(String taskName) {
this.delegate.doTask(taskName);
}


}
4.代理工厂类

/**
* 代理工厂
*
* @author XiaoYun 2013-07-13
*/
public class SubjectDynamicProxyFactory {

public static Subject getSubject() {
Subject proxy = null;
//得到实际逻辑实现类
Subject delegate = new RealSubject();
//得到代理类
InvocationHandler hander = new ProxySubject(delegate);
//根据该实现类的类加载器,代理类接口,代理类实际程序接口得到代理对象
proxy = (Subject)Proxy.newProxyInstance(delegate.getClass().getClassLoader(),
delegate.getClass().getInterfaces(), hander);
return proxy;
}
}
5.测试类
/**
* 动态代理测试
*
* @author XiaoYun 2013-07-13
*/
public class Client {
public static void main(String[] args) {
Subject delegate = SubjectDynamicProxyFactory.getSubject();
delegate.doTask1("任务一");
delegate.doTask2("任务二");
delegate.doTask3("任务三");
}
}
关于运行结果,希望大家自己先想一下应该是一个什么结果,然后再运行。其实我也想引用马士兵老师的一句话,学习的规律是先学习使用用,然后去了解底层实现,当然我认为其实能先理解原理更好,如果理解不了也没关系,写多了,自己多做总结,多思考,自然而然的就能领悟到其中的原理了,反正这是我的心得,希望对一些初学者有帮助,我也是刚用java大概有一年时间。
代码至此告一段落,动态代理原理即时如此。当然我学习到的可能也不完整,毕竟只花了半个下午的时间来做这件事儿。
项目中用到的代理可以节约很多时间和多余的工作,所以学习下还是不错的。在这之前,我也经常在iteye上浏览别人的博客,一直都知道动态代理应该算是java中比较高级的部分了,终于我自己也在iteye上发了一篇,都是自己的心得。大家有什么疑问和建议欢迎给我留言,大家一起进步,学习的不足的地方还请前辈们不吝赐教。肖云
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值