动态代理属于Java反射的一种。

当我们得到一个对象,想动态的为其一些方法每次被调用前后追加一些操作时,我们将会用到java动态代理。

下边上代码:

首先定义一个接口:

package com.liuyx;

public interface Itf {
public abstract void printMe(); public abstract void printSth(String me);
}

接着是它的实现:

package com.liuyx;

public class Cls implements Itf {

    @Override
public void printMe() {
System.out.println("I'm Cls!");
} @Override
public void printSth(String str) {
System.out.println(str);
} }

我们的目的就是通过动态代理技术,在Cls这个类的对象的两个方法执行前后,加上一些打印操作。

现在我们实现一个InvocationHandler,把我们想要通过代理者被代理者追加的操作都写在invoke方法里面:

package com.liuyx;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class StandardInvocation implements InvocationHandler { private Object obj; StandardInvocation(Object obj){
this.obj=obj;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before method excute!");
Object result = method.invoke(obj, args);
System.out.println("after method excute!");
return result;
} }

首先、这里面有一个obj,这个obj是必须的,我们既然要做代理,我们必须知道我们是给谁做代理,这里的obj就是被代理者。

动态代理说到底也是代理,代理模式里就要求有一个被代理者。

然后是invoke的三个参数、第一个参数就是代理者,如果你想对代理者做一些操作可以使用这个参数;第二个就是被执行的方法,第三个是执行该方法所需的参数。

当你执行代理者的某个方法的时候,最后跑的都是invoke方法。

然后是用法:

    public static void main(String[] args) {
//创建一个被代理者
Cls c = new Cls();
//创建一个InvocationHandler,描述我们希望代理者执行哪些操作
InvocationHandler i = new StandardInvocation(c);
//通过刚才创建的InvocationHandler,创建真正的代理者。第一个参数是类加载器,第二个参数是这个代理者实现哪些接口
Itf pxy = (Itf) Proxy.newProxyInstance(Cls.class.getClassLoader(), new Class[] { Itf.class }, i);
pxy.printSth("Hi");
}

pxy就是c的代理者。

最后来一个稍微改进的写法:

package com.liuyx;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class InvocationHandlerTest implements InvocationHandler { private Object target; Object bind(Object i) {
target = i;
Object warpedItf;
warpedItf = Proxy.newProxyInstance(target.getClass().getClassLoader(), i.getClass().getInterfaces(), this);
return warpedItf;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before method excute!");
method.invoke(target, args);
System.out.println("after method excute!");
return null;
} public static void main(String[] args) {
Cls c = new Cls();
InvocationHandlerTest pxy = new InvocationHandlerTest();
Itf itf = (Itf)pxy.bind(c);
itf.printSth("Hello");
} }

java动态代理有一定局限性,需要定义至少一个接口,使用cglib则不必如此。

最新文章

  1. C# Thread.Join()用法的理解 转
  2. LeetCode:Remove Duplicates from Sorted List I II
  3. 实用防火墙(Iptables)脚本分析
  4. UISegmentedControl 分段器加载不同的viewcontroller
  5. 《bunzip2命令》-linux命令五分钟系列之八
  6. 【转】linux内核调试技巧之一 dump_stack
  7. C-二维数组,多维数组
  8. JavaScript设计模式_03_代理模式
  9. YYHS-NOIP模拟赛-gcd
  10. 网站开发中使用javascript获取浏览器滚动条宽度
  11. 细述:nginx http内核模块提供的变量和解释
  12. 极光推送(C#)
  13. IOS - 修改APP桌面名称为中文名称!
  14. WPF Blend 脑洞大开的问题:如何用Blend得到或画出一个凹槽、曲面。
  15. java连接mysql的过程
  16. django使用restframework实现安全的api
  17. POI中文API文档
  18. web前端开发分享-css,js入门篇
  19. pragma comment的使用(转)
  20. 如何利用反射简化Servlet操作

热门文章

  1. python开发_搜索本地文件信息写入文件
  2. STM32 Hardware Development
  3. 对 dpif_class 结构体的一点认识
  4. Jquery实现可拖拽的树菜单
  5. C# 怎么获取所有打开的窗体
  6. ASP.NET MVC:看 MVC 源码,学习:如何将 Area 中的 Controller 放到独立的程序集?
  7. 怎样解决MySQL数据库主从复制延迟的问题
  8. Istio在Openshift 3.11的安装
  9. iOS开源项目:SVPullToRefresh
  10. iOS:切换视图时,反向传递数据方法一:通知