动态代理,是java支持的一种程序设计方法。

动态代理实现中有两个重要的接口和类,分别是InvocationHandler(interface),Proxy(class).

要实现动态代理,必须要定义一个被代理类的接口Interface,另外,被代理类必须实现这个接口,这样,在代理类生存过程中,就可以通过接口,反射的方式找到这个被代理类。这个和代理模式中要求基本一致:代理类和被代理类都必须实现同一个接口。只是这里,有点点不同,只是要求被代理类必须定义一个接口,而代理类依据被代理类接口通过反射的机制找到这个被代理类的实现。有点绕,静下心理一理,还是比较容易弄清的!

下面就用一个动态代理的例子来呈现其原理吧。

1.首先是被代理类的接口定义。

 package dynamic_proxy;

 /**
* 动态代理,必须有一个公共的接口,这个也是代理模式的基本要求
*
* @author shihuc
* @date Mar 17, 2016
*
*/
public interface Happy { public void sayHello(); public void makeFriends(String guNiang);
}

2.被代理类的具体实现

 package dynamic_proxy;
/**
*
* 被代理的类,必须实现公共的接口,要有自己的特色活要干,比如这里,西门庆后面要被王婆代理,
* 但是西门庆最终还是要上阵干活,泡潘金莲啊。只是外表上,让人看起来是王婆在作媒人。。。
*
* @author shihuc
* @date Mar 17, 2016
*
*/ public class Ximenqing implements Happy{ public void sayHello() {
System.out.println("Hi, I am Ximenqing");
} public void makeFriends(String guNiang) {
System.out.println("Hello, " + guNiang + ", I am Ximenqing!");
} }

3. 代理类的实现。这里很重要,代理类必须实现InvocationHandler这个Interface,并且实现里面的invoke函数。

 package dynamic_proxy;

 import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; /**
*
* 王婆开始代理西门庆上场了,注意,这里只是表面上看是王婆代理,但是,王婆其实只是牵线搭桥,比如,
* 将Happy这个接口的实例ximenqing传进代理,后面干活的,还是这个西门庆哟!
*
* @author shihuc
* @date Mar 17, 2016
*
*/
public class PaoniuHandler implements InvocationHandler{ Happy happy; public PaoniuHandler(Happy happy){
this.happy = happy;
} public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //在这里,你可以加入真实函数执行前的辅助逻辑。
System.out.println("Here, ‘BEFORE’ you can add your supplemental logic"); //反射的机制实现对真是的被代理的函数进行执行操作
method.invoke(happy, args); //在这里,你可以加入真是逻辑执行完成后的一些处理逻辑
System.out.println("Here, 'AFTER' you can add some logic for you completed real logic"); return null;
}
}

4. 下面用一个小测试程序,检测一下上面的动态代理的执行过程。

 package dynamic_proxy;

 import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy; /**
* 动态代理的具体运行步骤。重点是通过Proxy类来生成代理类的实例wangpo。这里的生成过程,和代理模式不同,这里是依据Proxy类的类函数newProxyInstance得到的。
* static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
* JDK1.6对上面这个函数的解释:“返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。”
*
* @author shihuc
* @date Mar 18, 2016
*
*/
public class Client { public static void main(String args[]){ //真正干活的人,西门庆的诞生
Happy ximenqing = new Ximenqing(); //创建代理类处理程序,在这里,需要传递进被代理者,也就是泡妞的主体西门庆。
InvocationHandler xmqHandler = new PaoniuHandler(ximenqing); /*代理者wangpo出场的核心程序。
* Proxy类的newProxyInstance通过用户指定的类加载器xmqHandler.getClass().getClassLoader(),
* 代理类要实现的接口列表ximenqing.getClass().getInterfaces(),
* 代理类指派方法调用的调用处理程序(也就是说,代理类基于Happy接口生成代理类,这个代理类要做的事情是InvocationHandler实现者里指定被代理者做的事情。
* 说白了,就是王婆帮西门庆出去搭讪潘金莲了,但是核心婆妞的事情还是西门庆上。)
*/
Happy wangpo = (Happy)Proxy.newProxyInstance(xmqHandler.getClass().getClassLoader(), ximenqing.getClass().getInterfaces(), xmqHandler); //王婆搭讪潘金莲了。其实后手是西门庆。
wangpo.makeFriends("Ms Pan Jinlian"); }
}

下面看看执行的输出:

 Here, ‘BEFORE’ you can add your supplemental logic
Hello, Ms Pan Jinlian, I am Ximenqing!
Here, 'AFTER' you can add some logic for you completed real logic

到这里,动态代理的实现全部完成。是不是没有想象的那么复杂,关于核心InvocationHandler以及Proxy的newProxyInstance的具体实现,可以google,很多的!

接下来,看看如何基于动态代理,实现基于动态代理的AOP。其实改动的地方很小,下面给一个简单的例子,基于上面的例子做了点改动。

 package dyn_pxy_aop;

 /**
* 动态代理,必须有一个公共的接口,这个也是代理模式的基本要求
*
* @author shihuc
* @date Mar 17, 2016
*
*/
public interface Happy { public void sayHello(); public void makeFriends(String guNiang);
}
 package dyn_pxy_aop;
/**
*
* 被代理的类,必须实现公共的接口,要有自己的特色活要干,比如这里,西门庆后面要被王婆代理,
* 但是西门庆最终还是要上阵干活,泡潘金莲啊。只是外表上,让人看起来是王婆在作媒人。。。
*
* @author shihuc
* @date Mar 17, 2016
*
*/ public class Ximenqing implements Happy{ public void sayHello() {
System.out.println("Hi, I am Ximenqing");
} public void makeFriends(String guNiang) {
System.out.println("Hello, " + guNiang + ", I am Ximenqing!");
} }
 package dyn_pxy_aop;

 import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; /**
*
* 王婆开始代理西门庆上场了,注意,这里只是表面上看是王婆代理,但是,王婆其实只是牵线搭桥,比如,
* 将Happy这个接口的实例ximenqing传进代理,后面干活的,还是这个西门庆哟!
*
* @author shihuc
* @date Mar 17, 2016
*
*/
public class PaoniuHandler implements InvocationHandler{ Happy happy; public PaoniuHandler(Happy happy){
this.happy = happy;
} public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //反射的机制实现对真是的被代理的函数进行执行操作
method.invoke(happy, args); return null;
}
}
 package dyn_pxy_aop;

 import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; /**
* 王婆的代理,其产生的机制,就非常的明显了,基于反射获取Happy的方法,然后直接利用InvocationHandler的invoke方法进行方法调用,
* 更进一步的显示出真正干活的是谁了(西门庆)
*
* @author shihuc
* @date Mar 18, 2016
*
*/
public class WangpoProxy implements Happy{ InvocationHandler paoniuHandler; public WangpoProxy(InvocationHandler h){
this.paoniuHandler = h;
} public void sayHello() {
try {
Method m = ((PaoniuHandler)paoniuHandler).happy.getClass().getMethod("sayHello", null);
paoniuHandler.invoke(this, m, null);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public void makeFriends(String guNiang) {
try {
Method m = ((PaoniuHandler)paoniuHandler).happy.getClass().getMethod("makeFriends", new Class[]{String.class});
paoniuHandler.invoke(this, m, new Object[]{guNiang});
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
 package dyn_pxy_aop;

 /**
* 所谓的AOP,最终的目的就是在不修改原有的业务代码的基础上,在原有逻辑的前(before),后(after),以及前和后(around)的位置,添加其他的功能(advice),比如日志,事物,安全等
*
* @author shihuc
* @date Mar 18, 2016
*
*/
public class AOP_demo { public static void main(String[] args) { PaoniuHandler ph = new PaoniuHandler(new Ximenqing());
//这里可以加入advice
new WangpoProxy(ph).sayHello();
new WangpoProxy(ph).makeFriends("Pan Jinlian");
//这里可以加入advice
} }

基于动态代理实现的AOP,其实有个很明显的不足,就是过于依赖反射,这就必然影响性能。但是它也有个明显的优势,就是实现起来灵活。

AOP的实现,除了基于动态代理的方案,还有动态字节码生成方案,静态AOP等等,可以慢慢研究,根据需要进行取舍!

动态代理到基于动态代理的AOP的更多相关文章

  1. Web静态和动态项目委托代理基于面向方面编程AOP

    本来每天更新,我一般喜欢晚上十二点的时候发文章,结果是不是愚人节?校内网也将是非常有趣,破,把我给打. ..好吧-从今天开始的话题AOP.AOP太重要了,所以把第二篇文章谈论这个话题,AOP它是Spr ...

  2. 最简单的动态代理实例(spring基于接口代理的AOP原理)

    JDK的动态代理是基于接口的 package com.open.aop; public interface BusinessInterface {     public void processBus ...

  3. Spring AOP源码分析(三):基于JDK动态代理和CGLIB创建代理对象的实现原理

    AOP代理对象的创建 AOP相关的代理对象的创建主要在applyBeanPostProcessorsBeforeInstantiation方法实现: protected Object applyBea ...

  4. .NET 下基于动态代理的 AOP 框架实现揭秘

    .NET 下基于动态代理的 AOP 框架实现揭秘 Intro 之前基于 Roslyn 实现了一个简单的条件解析引擎,想了解的可以看这篇文章 https://www.cnblogs.com/weihan ...

  5. 实现一个简单的基于动态代理的 AOP

    实现一个简单的基于动态代理的 AOP Intro 上次看基于动态代理的 AOP 框架实现,立了一个 Flag, 自己写一个简单的 AOP 实现示例,今天过来填坑了 目前的实现是基于 Emit 来做的, ...

  6. Spring AOP详解 、 JDK动态代理、CGLib动态代理

    AOP是Aspect Oriented Programing的简称,面向切面编程.AOP适合于那些具有横切逻辑的应用:如性能监测,访问控制,事务管理以及日志记录.AOP将这些分散在各个业务逻辑中的代码 ...

  7. 何为代理?jdk动态代理与cglib代理、spring Aop代理原理浅析

    原创声明:本博客来源为本人原创作品,绝非他处摘取,转摘请联系博主 代理(proxy)的定义:为某对象提供代理服务,拥有操作代理对象的功能,在某些情况下,当客户不想或者不能直接引用另一个对象,而代理对象 ...

  8. 【转载】Spring AOP详解 、 JDK动态代理、CGLib动态代理

    Spring AOP详解 . JDK动态代理.CGLib动态代理  原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspec ...

  9. 基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别。

    基于JDK动态代理和CGLIB动态代理的实现Spring注解管理事务(@Trasactional)到底有什么区别. 我还是喜欢基于Schema风格的Spring事务管理,但也有很多人在用基于@Tras ...

随机推荐

  1. iOS-XMPP客户端

    首先我们自己做一个的IOS客户端程序 先看一下我们完成的效果图 首先下载xmppframework这个框架 点ZIP下载 接下来,用Xcode新建一个工程 将以下这些文件拖入新建工程中 加入frame ...

  2. linxu c语言 fcntl函数和flock函数区别 【转】

    flock和fcntl都有锁的功能,但他们还有一点小小的区别: 1.flock只能加全局锁,fcntl可以加全局锁也可以加局部锁. 2.当一个进程用flock给一个文件加锁时,用另一个进程再给这个文件 ...

  3. Hashing filters for very fast massive filtering

    If you have a need for thousands of rules, for example if you have a lot of clients or computers, al ...

  4. 如何让Visual Studio 清除最近打开项目 关闭上次未关闭的标签窗口

    删除最近打开的文件: 打开HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\FileMRUList 删除最近打开的项目: 打开HKEY_CUR ...

  5. [转]SQL:JOIN用法

    JOIN连接组合两个表中的字段记录,包括三种: INNER JOIN运算式:连接组合两个表中的字段记录. LEFT JOIN运算式:连接组合两个表中的字段记录,并将包含了LEFT JOIN左边表中的全 ...

  6. 计算机中如何表示数字-07IEEE754浮点数标准

    由于不同机器所选用的基数.尾数位长度和阶码位长度不同,因此对浮点数的表示有较大差别,这不利于软件在不同计算机之间的移植.为此,美国IEEE(电器及电子工程师协会)提出了一个从系统角度支持浮点数的表示方 ...

  7. hdu2546 饭卡    01背包

    link:http://acm.hdu.edu.cn/showproblem.php?pid=2546 也算一个贪心的想法吧. 先把总钱数减去5,再把价值最大的挑出来.然后用01背包.最终买下挑出来的 ...

  8. JS初学之-选项卡(常见)

    思路:鼠标滑过的效果直接用a:hover实现的,比较简便,缺点是在IE下不兼容.   为每一个Li添加点击事件,将每一个li用自定义属性的方法与div相匹配,重点是在点击事件内,要先遍历每一个div, ...

  9. Codeforces Round #134 (Div. 2)

    A. Mountain Scenery 枚举山顶位置,满足\(r_{i-1} \lt r_i - 1 \gt r_{i+1}\). 范围要开\(2N\). B. Airport 优先队列维护最值. C ...

  10. 求解:php商品条件筛选功能你是怎么做出来的?

    求解:php商品条件筛选功能你是怎么做出来的? 2013-09-25 13:43 chenhang607 | 浏览 2756 次 资源共享 求思路或者方法,最好能有些代码 2013-09-25 14: ...