java动态代理

原创 2016年10月20日 14:24:51

转载请标明出处:http://blog.csdn.net/shensky711/article/details/52872249
本文出自: 【HansChen的博客】

概述

动态代理是java的一大特性,动态代理的优势就是实现无侵入式的代码扩展。它可以增强我们原有的方法,比如常用的日志监控,添加缓存等,也可以实现方法拦截,通过代理方法修改原方法的参数和返回值等。
要了解动态代理,我们需要先看看什么是静态代理

静态代理

首先你有一个接口:

public interface Api {

    String doSomething(String input);
}

这个接口有一个原始的实现:

public class ApiImpl implements Api {

    @Override
    public String doSomething(String input) {
        return input + "原始方法";
    }
}

现在问题来了,有一个新的需求,我需要在所有调用doSomething的地方都添加一个log,那怎么办呢?我们当然可以在原有代码上直接加上log,但是ApiImpl里面的log真的是那段代码需要的吗?如果不修改原有代码,能不能实现?当然可以,如,我们添加一个代理类:

public class ApiProxy implements Api {

    private Api mBase;

    public ApiProxy(Api base) {
        mBase = base;
    }

    @Override
    public String doSomething(String input) {
        System.out.println("someone call me~");
        return mBase.doSomething(input);
    }
}

这样,通过ApiProxy我们就是实现静态代理,这里只是简单的添加了log,我们完全可以在ApiProxy的doSomething方法里面,篡改输入参数input以及返回值,从而做一些坏事~

动态代理

在上面静态代理例子中,我们已经实现了代理的功能,那为何还需要动态代理呢?设想一下以下两种情况

  • 如果Api接口类中有100个方法,需要为每个方法都添加log
  • 项目中有100个类,需要为每个类的方法都添加log

对于第一种情况,如果使用静态代理,那就只能这样了:

public class ApiProxy implements Api {

    private Api mBase;

    public ApiProxy(Api base) {
        mBase = base;
    }

    @Override
    public String doSomething(String input) {
        System.out.println("someone call me~");
        return mBase.doSomething(input);
    }

    @Override
    public String doSomething1(String input) {
        System.out.println("someone call me~");
        return mBase.doSomething1(input);
    }

    //为每个方法添加实现......
}

而对于第二种情况,就只能新建100个代理类了。这种处理方式肯定不是我们喜欢的,怎么优雅地去解决了?动态代理这时候终于可以上场了。

JDK提供了动态代理方式,可以简单理解为JVM可以在运行时帮我们动态生成一系列的代理类,这样我们就不需要手写每一个静态的代理类了,比如:

  1. 实现InvocationHandler
public class ApiHandler implements InvocationHandler {

    private Api mBase;

    public ApiHandler(Api base) {
        mBase = base;
    }

    /**
     * 此方法会在proxy实例调用方法的时候回调
     *
     * @param proxy  代理对象
     * @param method 被调用的方法
     * @param args   调用参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("someone call me~");
        return method.invoke(mBase, args);
    }
}
  1. 动态创建代理类
    private static void proxyTest() {
        ClassLoader loader = Api.class.getClassLoader();//加载代理类的ClassLoader
        Class[] interfaces = new Class[]{Api.class};//需要代理的接口
        Api proxy = (Api) Proxy.newProxyInstance(loader, interfaces, new ApiHandler(new ApiImpl()));//创建代理对象
        proxy.doSomething("test");//会调用ApiHandler的invoke方法
        proxy.doSomething1("test");//会调用ApiHandler的invoke方法
    }

这样,一个动态代理就完成了,但这里有个需要注意的,动态代理只能代理接口,也就是说interfaces数组里面,只能放接口Class

代理Hook

代理有比原始对象更强大的能力,如果我们自己创建代理对象,然后把原始对象替换为我们的代理对象,那么就可以在这个代理对象为所欲为了;修改参数,替换返回值,我们称之为Hook。
首先我们得找到被Hook的对象,也就是Hook点;什么样的对象比较适合Hook呢?静态变量和单例;在一个进程之内,静态变量和单例变量是不容易发生变化的,所以容易定位,而普通的对象则要么无法标志,要么容易改变,我们根据这个原则找到所谓的Hook点。
一般Hook的步骤有:

  1. 寻找Hook点,如静态变量或单例对象,尽量Hook pulic的对象和方法,非public不保证每个版本都一样,需要适配。
  2. 选择合适的代理方式,如果是接口可以用动态代理;如果是类可以手动写代理也可以使用cglib
  3. 用代理对象替换原始对象,如果没有公开是geter/setter方法,可以使用反射
版权声明:本文为博主原创文章,转载请标明出处,谢谢

Java动态代理、cglib动态代理

说动态代理,需要先清楚静态代理。所谓静态代理就是程序员提前实现好的代理类,编译后class文件是已经存在的。 实现原理,利用Java代理模式,由一个代理类持有委托类的实例,并实现委托类一样的接口,来...
  • catoop
  • catoop
  • 2016年02月24日 14:17
  • 2710

[Java] 静态代理 - 动态代理 01

什么叫代理? 什么是静态代理?什么是动态代理?  我觉得用代码可以解释这一切。。  直接看代码:  Java动态代理模式  代理:一个角色代表别一个角色来完成某些特定的功能。     比如:生产商,中...
  • robby_chan
  • robby_chan
  • 2014年01月19日 10:40
  • 1044

java静态代理和动态代理

一、代理概念 为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类...
  • u011776918
  • u011776918
  • 2013年12月08日 12:41
  • 8589

Java动态代理(JDK和cglib)

  • 2017年07月04日 21:10
  • 246KB
  • 下载

JAVA反射机制和动态代理PDF

  • 2012年12月13日 14:55
  • 263KB
  • 下载

java动态代理

  • 2012年04月30日 21:04
  • 2KB
  • 下载

java 动态代理 简单实例

  • 2011年12月24日 13:52
  • 6KB
  • 下载

java动态代理

  • 2012年10月06日 10:37
  • 2KB
  • 下载

java 动态代理实现AOP

  • 2012年05月17日 14:30
  • 139KB
  • 下载

使用java动态代理技术实现简单的AOP切面编程实例

  • 2017年03月05日 18:15
  • 14KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java动态代理
举报原因:
原因补充:

(最多只允许输入30个字)