写在前面:
大神和diao炸天的亲请绕道..
关于代理模式的概念这里省去,大家可以放鸟尽情搜..
关于为什么叫动态代理,个人理解是代理的类是在运行时动态生成的,大家也可以参考网上的理解..
文笔很差,所以文字较少,都在代码和注释中..
=======一点不华丽的分割线-------------------------
开门见山,lets go..
java中可以通过jdk提供的 Proxy.newProxyInstance静态方法来创建动态代理对象,下面先来看看这个方法的实现
- public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
- throws IllegalArgumentException {
- //InvocationHandler不能为空,因为对代理对象的所有方法调用实际上都会委托到InvocationHandler的invoke方法,
- //这个我们后面通过查看产生的代理类的源代码便会一目了然
- if (h == null) {
- throw new NullPointerException();
- }
- //这个是核心的地方,通过提供的ClassLoader和interface列表来产生代理类,具体的实现可以参考getProxyClass这个方法的实现,
- //真正的工作是由sun.misc.ProxyGenerator这个类来完成的,可以google查看具体的逻辑.在我们的程序中通过设置
- //System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true")可以查看产生的类文件
- Class cl = getProxyClass(loader, interfaces);
- //因为代理类继承了Proxy类.而Proxy中定义了构造函数protected Proxy(InvocationHandler h),所以可以反射得到Constructer实例
- //创建代理对象
- try {
- Constructor cons = cl.getConstructor(constructorParams);
- return (Object) cons.newInstance(new Object[] { h });
- } catch (NoSuchMethodException e) {
- throw new InternalError(e.toString());
- } catch (IllegalAccessException e) {
- throw new InternalError(e.toString());
- } catch (InstantiationException e) {
- throw new InternalError(e.toString());
- } catch (InvocationTargetException e) {
- throw new InternalError(e.toString());
- }
- }
下面通过个例子来说明下:
先来定义一个接口,jdk的动态代理基于接口来创建代理类,不能基于类的原因是java不支持多重继承,而代理类都会继承Proxy类(个人理解).
- /**
- * Subject
- *
- * @author Kevin Fan
- * @since 2013-9-13 下午2:43:33
- */
- public interface Subject {
- void pub(String key, String content);
- String sub(String key);
- }
再来一个具体的实现,在代理模式中可以叫它的实例可以叫target,这个是真正执行操作的对象
- /**
- * SimpleSubject
- *
- * @author Kevin Fan
- * @since 2013-9-13 下午2:45:03
- */
- public class SimpleSubject implements Subject {
- private Map<String, String> msg = new ConcurrentHashMap<String, String>();
- public void pub(String key, String content) {
- System.out.println("pub msg: key is " + key + ", content is " + content);
- msg.put(key, content);
- }
- public String sub(String key) {
- if (msg.containsKey(key)) {
- String ret = msg.get(key);
- System.out.println("sub msg: key is " + key + ", result is " + ret);
- return ret;
- }
- return null;
- }
- }
好,接下来我们来写个动态代理工厂,根据 不同的target来创建动态代理对象
- /**
- * SubjectProxyFactory
- *
- * @author Kevin Fan
- * @since 2013-9-13 下午2:47:24
- */
- public class SubjectProxyFactory {
- //TODO: cache
- public static Subject getSubject(final Subject realSubject) {
- return (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), new Class[] { Subject.class },
- new InvocationHandler() {
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- System.out.println("\naction before method invocation....");
- Object retVal = method.invoke(realSubject, args);
- System.out.println("action after method invocation....\n");
- return retVal;
- }
- });
- }
- }
可以看到这是一个简单的实现,只是在真实对象执行前后各打一句信息..
接下来用一个 main函数来把这些结合起来
- /**
- * Demo
- *
- * @author Kevin Fan
- * @since 2013-9-13 下午2:50:28
- */
- public class Demo {
- public static void main(String[] args) {
- //设置此系统属性,以查看代理类文件
- System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
- //创建真实对象
- Subject subj = new SimpleSubject();
- subj.pub("name", "kevin.fan");
- subj.sub("name");
- //创建代理对象
- Subject proxy = SubjectProxyFactory.getSubject(subj);
- proxy.pub("hobby", "r&b music");
- proxy.sub("name");
- }
- }
ok,小手抖一下,走你,看下执行结果
- pub msg: key is name, content is kevin.fan
- sub msg: key is name, result is kevin.fan
- action before method invocation....
- pub msg: key is hobby, content is r&b music
- action after method invocation....
- action before method invocation....
- sub msg: key is name, result is kevin.fan
- action after method invocation....
可以看到在调用代理对象的方法时,添加的额外动作已经生效,接下来我们看下生成的代理类的代码..
- import com.aliyun.demo.kevin.coder.lang.proxy.Subject;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- import java.lang.reflect.UndeclaredThrowableException;
- //这里很清楚了,代理类继承了Proxy类,并且实现了Proxy.newProxyInstance这个方法中传入的接口
- public final class $Proxy0 extends Proxy
- implements Subject
- {
- //这些方法在下面的static init block中进行初始化
- private static Method m4;
- private static Method m1;
- private static Method m3;
- private static Method m0;
- private static Method m2;
- static
- {
- try
- {
- m4 = Class.forName("com.aliyun.demo.kevin.coder.lang.proxy.Subject").getMethod("sub", new Class[] { Class.forName("java.lang.String") });
- m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
- m3 = Class.forName("com.aliyun.demo.kevin.coder.lang.proxy.Subject").getMethod("pub", new Class[] { Class.forName("java.lang.String"), Class.forName("java.lang.String") });
- m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
- m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
- return;
- }
- catch (NoSuchMethodException localNoSuchMethodException)
- {
- throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
- }
- catch (ClassNotFoundException localClassNotFoundException)
- {
- throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
- }
- }
- //构造函数,接收一个 InvocationHandler作为参数,这就是为什么Proxy.newProxyInstance方法里可以
- //通过InvocationHandler实例作为参数来反射获取Constructer实例
- public $Proxy0 paramInvocationHandler)
- throws
- {
- super(paramInvocationHandler);
- }
- //下面通过这个来看下代理对象中方法是怎样调用的
- public final String sub(String paramString)
- throws
- {
- try
- {
- //全部是通过调用InvocationHandler的invoke方法,传入对应的方法和参数
- return (String)this.h.invoke(this, m4, new Object[] { paramString });
- }
- catch (Error|RuntimeException localError)
- {
- throw localError;
- }
- catch (Throwable localThrowable)
- {
- throw new UndeclaredThrowableException(localThrowable);
- }
- }
- public final boolean equals(Object paramObject)
- throws
- {
- try
- {
- return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
- }
- catch (Error|RuntimeException localError)
- {
- throw localError;
- }
- catch (Throwable localThrowable)
- {
- throw new UndeclaredThrowableException(localThrowable);
- }
- }
- public final void pub(String paramString1, String paramString2)
- throws
- {
- try
- {
- this.h.invoke(this, m3, new Object[] { paramString1, paramString2 });
- return;
- }
- catch (Error|RuntimeException localError)
- {
- throw localError;
- }
- catch (Throwable localThrowable)
- {
- throw new UndeclaredThrowableException(localThrowable);
- }
- }
- public final int hashCode()
- throws
- {
- try
- {
- return ((Integer)this.h.invoke(this, m0, null)).intValue();
- }
- catch (Error|RuntimeException localError)
- {
- throw localError;
- }
- catch (Throwable localThrowable)
- {
- throw new UndeclaredThrowableException(localThrowable);
- }
- }
- public final String toString()
- throws
- {
- try
- {
- return (String)this.h.invoke(this, m2, null);
- }
- catch (Error|RuntimeException localError)
- {
- throw localError;
- }
- catch (Throwable localThrowable)
- {
- throw new UndeclaredThrowableException(localThrowable);
- }
- }
- }
相关推荐
主要介绍了Java JDK动态代理实现原理实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
动态代理是使用jdk的反射机制,创建对象的...jdk动态代理,必须有接口,目标类必须实现接口, 没有接口时,需要使用cglib动态代理。 动态代理可以在不改变原来目标方法功能的前提下, 可以在代理中增强自己的功能代码。
JDK动态代理的底层实现原理
代理模式的优点二、jdk动态代理实现原理1. jdk动态代理源码分析(通过该示例学会阅读源码的方法)2.jdk动态代理生成的代理类的源码3.总结三、手写实现jdk动态代理 一、代理模式 熟悉代理模式的可以直接点击目录第二章...
Spring Aop的底层实现技术 --- Jdk动态代理原理 很不错的一篇文章
代理模式详解-jdk与cglib动态代理与底层实现,spring中常用的设计模式,本案例是从源码到代理模式的实现。
AOP的意思就是面向切面编程。本文主要是通过梳理JDK中自带的反射机制,实现 AOP动态代理模式,这也是Spring AOP 的实现原理
文章目录一、代理模式定义二、代理模式的结构和说明三、代理模式的分类四、代理模式示例五、动态代理1、JDK动态代理JDK动态代理使用步骤JDK动态代理示例JDK动态代理实现原理JDK动态代理局限性2、CGLIB动态代理CGLIB...
JDK动态代理: 我们将详细介绍JDK动态代理的概念和工作原理。您将了解如何使用Java的反射机制来创建代理对象,以及如何将横切逻辑注入到目标方法中。我们还提供了实际示例,演示如何在Spring AOP中使用JDK动态代理。...
剖析java动态代理实现机制,只有明白了原理才会应用。详细请看代码
spring中动态代理机制的实现原理及AOP实现原理,JDK的反射,cglib类。
动态代理在 Java 中有着广泛的应用,比如 AOP 的实现原理、RPC远程调用、Java 注解对象获取、日志框架、全局性异常处理、事务处理等。 在了解动态代理前,我们需要先了解一下什么是代理模式。 代理模式 代理模式...
Java动态代理的实现 1 程序架构 创建包proxy.jdk,里面包含下面类和接口,详见批注。 类,实现了UserDao接口接口类测试类,包含main方法 类,实现了UserDao接口 接口 类 测试类,包含main方法 2 功能需求 (1) ...
该思维导图主要讲解了代理模式的具体实现,包括...其中jdk代理主要讲解了其具体的实现方式、原理、缺点、缓存机制等。Cglib代理主要讲解了其原理、与JDK代理的对比、Enhancer源码解析、methodProxy和Fastclass源码等。
里面是自己实现struts拦截器的一个原理,基于jdk的动态代理
如果一个类实现了一个或多个接口,那么Spring就会使用默认的JDK动态代理,如果没有实现任何接口,就会使用cglib来代理。当然我们也可以手动改变这些设置。这也是比较容易掉坑的部分,如果设置错了代理方式,那么在...
JDK动态代理。 Spring 的扫描原理(@CompanScan,@MapperScan 同理) Spring的事件监听与处理, 反射,SpringListener 配置,负债均衡随机算法。 通过Spring注解形式启用RPC,接口暴露扫描,Rpc接口注解引用。 ...
jdk和cglib实现的AOP实际上会在内存生成动态代理对象,还有什么其他办法实现AOP?经提示答出AspectJ以及实现原理 Spring中的对象的作用域 Singleton对象引用Prototype会发生什么 项目中怎样使用微服务? 两个服务...
Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是...Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象pro
它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。 二、CGLIB原理 CGLIB原理:动态...