- 浏览: 149328 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (166)
- Spring (7)
- JavaSE (16)
- web (1)
- Struts2 (2)
- Maven (1)
- 面试 (8)
- Hibernate (4)
- mysql (2)
- WebSerice (2)
- 工作心得 (23)
- 北京 (1)
- 上海 (27)
- groovy (1)
- 生活 (9)
- Linux (12)
- junit (1)
- oracle (5)
- h2db嵌入式数据库 (1)
- redis (14)
- 生活感悟 (1)
- cron (1)
- tomcat (4)
- 设计模式 (7)
- 正则表达式 (1)
- html5 (2)
- 网络编程 (3)
- 微信公众号 (1)
- Java nio (5)
- jdbc (1)
- 框架漏洞 (1)
- 安全 (8)
- 分布式 (2)
- 数据结构 (5)
- xml,json (0)
- xml (1)
- json (1)
- netty (0)
- java8 (1)
- javascript (1)
- 2016计划 (1)
- Java集合源码分析 (1)
- 工作心得,jvm性能调优 (3)
- 转载 (14)
- 产品 (1)
- JVM (10)
最新评论
-
oplife:
都不太难
返利网面试 -
飞翔神话:
谢谢 7 楼 cnrainbing
联想中望面试心得体会 -
飞翔神话:
5 楼 home198979,相比您可能还差点,但是我还是有一 ...
联想中望面试心得体会 -
cnrainbing:
支持小伙子
联想中望面试心得体会 -
jahu:
这简单啊,
联想中望面试心得体会
昨天下午终于签好了合同。今天下午午觉醒来,便开始了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上发了一篇,都是自己的心得。大家有什么疑问和建议欢迎给我留言,大家一起进步,学习的不足的地方还请前辈们不吝赐教。肖云
首先,我们应该明白何为代理,所谓代理,按照我的理解,用户只需要知道接口中的方法名,不需要了解方法中的具体实现,就可以进行远程访问。
在应用上可以用在考试系统中,一个服务器,多个考试机调用服务器上面的方法,以及其他的一些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上发了一篇,都是自己的心得。大家有什么疑问和建议欢迎给我留言,大家一起进步,学习的不足的地方还请前辈们不吝赐教。肖云
发表评论
-
for循环删除(ArrayList.remove)报错及解决办法
2017-01-12 15:50 1795[size=small]代码: JSONArray bin ... -
Java的接口和抽象类区别
2016-07-23 15:10 3831.语法层面上的区别 ... -
transient关键字
2016-07-04 14:56 493transient的用途 Q:transient关键字能实现 ... -
Java中的继承与组合(转载)
2016-07-03 22:34 567本文主要说明Java中继承与组合的概念,以及它们之间的联系与区 ... -
volatile的作用和使用场景
2016-05-07 17:00 10711、线程可见性,volatile修饰的变量是存放在主内存区域, ... -
Java synchronized
2016-04-26 23:30 437一、当两个并发线程访问同一个对象object中的这个synch ... -
java对象的强引用,软引用,弱引用和虚引用
2016-03-24 22:56 552[size=x-small] 众所 ... -
Java链式编程
2016-01-24 22:42 2041简介:每个方法(接口)的返回值都是this(当前对象),调用多 ... -
jdk switch使用
2015-12-29 17:09 569jdk1.6及之前的jdk中switch中的变量有10种,分别 ... -
单例模式的两种方式
2013-08-28 21:36 863首先,单例模式是指在程序运行的过程中,保证该类的实例只有一 ... -
解决Java中浮点型数据计算时产生的精度误差
2013-08-18 21:06 2662关于double和float的精度问题,在进行数值运算时, ... -
Java自定义注解(原理和API)初探
2013-07-21 00:25 1694今天稍稍学习了 ... -
Java中反射和动态代理学习心得和总结
2013-07-18 23:19 761下面对反射和动态代理做下总结: 对于反 ... -
使用反射对类的私有方法和属性进行调用
2013-07-17 17:40 1699公司不忙,没事可做,springMVC没有调试成功,很郁 ... -
Java反射初探
2013-07-12 11:52 697目前非常多的开源 ...
相关推荐
Java JDK动态代理实现原理实例解析 Java JDK动态代理实现原理实例解析是指通过Java JDK提供的代理机制来实现动态代理的原理和实例解析。动态代理是一种非常重要的设计模式,它可以在运行时生成代理类,从而实现了...
本文将详细介绍JDK动态代理的原理与应用,帮助读者深入理解其工作方式以及如何在实际项目中运用。 #### 二、JDK动态代理简介 JDK动态代理是Java平台提供的一个工具包,用于在运行时创建代理对象。它主要适用于实现...
现在让我们深入探讨JDK动态代理和Spring AOP的原理。 首先,JDK动态代理基于Java的反射机制,通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类用于创建一个代理对象,...
- **只能代理实现了接口的类**:这是JDK动态代理的一个限制,如果目标对象没有实现任何接口,则无法使用JDK动态代理。 - **性能开销**:虽然这种开销通常很小,但在高并发场景下可能会成为瓶颈。 通过上述分析,...
在Java编程领域,JDK动态代理是一个非常重要的概念,它允许我们在...理解并掌握JDK动态代理的原理和用法,能够帮助我们更灵活地设计和实现程序,特别是在需要扩展或增强已有功能时,动态代理提供了一种优雅的解决方案。
Spring AOP 的底层实现技术 --- Jdk 动态代理原理 JDK 动态代理是 Spring AOP 的底层实现技术,允许开发者在运行期创建接口的代理实例。在 JDK 1.3 以后,JDK 动态代理技术提供了实现 AOP 的绝好底层技术。JDK 动态...
除了基本的代理实现,JDK动态代理还可以结合其他设计模式,如工厂模式,创建更加复杂的代理对象。此外,Spring框架中的AOP功能也是基于JDK动态代理或CGLIB实现的,它允许开发者定义切面,对满足特定条件的方法进行...
在本文中,我们将深入探讨如何模拟JDK的动态代理内部实现。 首先,我们需要了解JDK动态代理的基础知识。Java中的动态代理通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口实现。`Proxy...
- **JDK代理**适用于目标类实现有接口的情况,更符合面向接口的设计原则,且无需引入额外的库。 - **CGLIB代理**适用于目标类没有接口或者不希望修改原有接口的情况,其性能通常优于JDK代理,因为它是基于字节码生成...
JDK动态代理的底层实现原理
4. **底层实现原理**: - **JDK代理**:JDK动态代理使用反射和InvocationHandler接口生成一个实现了目标接口的新类。在运行时,这个新类的实例作为代理对象,它的方法调用都会转发到InvocationHandler的`invoke()`...
Java JDK 动态代理是一种强大的特性,它允许我们在运行时创建代理类,这些代理类可以扩展或修饰已存在的接口实现。动态代理在很多场景下非常有用,比如日志记录、性能监控、事务管理等,这些功能可以在不修改原始...
CGLIB和JDK动态代理是两种常用的实现方式,它们各有优缺点,适用于不同的场景。下面将详细探讨这两种动态代理的区别。 首先,JDK动态代理主要依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect....
下面将详细介绍JDK动态代理的工作原理及其实现方式。 ### 1. 动态代理概述 在Java中,动态代理主要由两个类完成:`java.lang.reflect.Proxy` 和 `java.lang.reflect.InvocationHandler`。`Proxy` 类用于创建一个...
首先,我们来理解JDK动态代理的工作原理。在Java中,动态代理通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类用于创建一个代理对象,该对象可以作为一个接口的实例,而...
一、JDK动态代理的基本原理 1. `Proxy`类:这个类是Java动态代理的入口,它提供了一种创建代理对象的方式。通过`Proxy.newProxyInstance()`方法,我们可以根据一个接口生成一个实现了该接口的代理对象。 2. `...
1. **JDK动态代理实现过程**: - 定义一个接口,被代理类实现该接口。 - 创建`InvocationHandler`实现类,重写`invoke`方法,此方法会在调用被代理类的任何方法时被调用。 - 使用`Proxy.newProxyInstance()`创建...
在Java编程中,JDK动态代理是一种非常重要的技术,它允许我们在运行时创建对现有接口的代理实现。这种技术在很多场景下都有广泛的应用,比如AOP(面向切面编程)、事务管理、缓存处理等。现在我们来深入探讨一下JDK...