动态代理,是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. C# <%@ Register %>指令

    将别名与命名空间及类名关联起来,以便在自定义服务器控件语法中使用简明的表示法. <%@ register tagprefix="tagprefix" namespace=&q ...

  2. C++调试技巧

    编号:1010时间:2016年5月13日11:15:20功能:C++调试技巧http://www.cnblogs.com/lidabo/p/3631055.html

  3. msp430 问题及解决记录

    ----------------------------- 2015.4.28 问题:开发板串口显示的内容为乱码 解决:使用的是原先产品主板的15200的波特率设置,但看来或者是开发板不支持11520 ...

  4. Link Aggregation and LACP with Open vSwitch

    In this post, I’m going to show you how to use link aggregation (via the Link Aggregation Control Pr ...

  5. iOS学习笔记---C语言第五天

    二维数组   字符串数组   多维数组 二维数组的定义 类型  数组[常量表达式1][常量表达式2]={值1,值2...}; int a[2][3] = {7,8,3,2,8,5}; #import ...

  6. WebSphere中对response.sendError()的处理与Tomcat不同

    不同的地方在于,同样的代码[response.sendError(1);] 在Tomcat下,response.getResponseCode()的值是 1,而在Websphere下面则是 500. ...

  7. spark1.5引进内置函数

    在Spark 1.5.x版本,增加了一系列内置函数到DataFrame API中,并且实现了code-generation的优化.与普通的函数不同,DataFrame的函数并不会执行后立即返回一个结果 ...

  8. ntpdate:no server suitable for synchronization found

    Question: 在使用ntpdate同步时间时,出现了no server suitable for synchronization found的报错. 通过ntpdate -d s2m.time. ...

  9. HDU-1561 The more, The Better (树形DP+分组背包)

    题目大意:给出一片森林,总共有n个点,并且都有权值.从中选出m个,使权值和最大.其中,选某个节点之前必须先选其父节点. 题目分析:给所有的树都加一个共同的权值为0的根节点,使森林变成一棵树.定义状态d ...

  10. 越狱Season 1-Episode 1: the pilot

    the pilot: 美国电视剧新剧开播都会有一个试播来测试观众对新剧的接受程度,以此来决定是否再继续播下去,也可以说是一个开端,第一集,试播 -Tattoo Artist: That's it. t ...