动态代理

来源:互联网 发布:领导力的文书 知乎 编辑:程序博客网 时间:2024/06/06 20:11

好久没有写blog了,回头看看上一次的blog时间是2012年2月,觉得还是很可惜的,中间空了三年没有写点东西,自己学过什么都没有留下笔记,不然现在现在记录的东西也是满满当当的吧。

空了的这三年我已经从.net转到了java,从传统软件行业转到了互联网,时间过得真快!

既然这次决定回归就会把blog写下去,第一篇是“动态代理”。


前段时间研究dubbo源码,里面基本上都用到了动态代理,虽然对这个东西还是有一知半解,但是我是很想彻底弄明白,本篇文章谈谈我对动态代理的理解。


1、代理模式

代理模式是软件开发中常用的设计模式之一,代理模式用于对外提供统一接口,而代理类在接口中实现对真实类的附加操作行为,从而可以在不影响外部调用情况下,进行系统扩展,如下图:


代理片段如下:

public interface ICalculator {public long add(long num1, long num2);public long subtract(long num1, long num2);}
public class Calculator implements ICalculator{public long add(long num1, long num2) {return num1 + num2;}public long subtract(long num1, long num2) {return num1 - num2;}}

public class CalculatorProxy implements ICalculator{private ICalculator calculator;public CalculatorProxy(ICalculator calculator){this.calculator = calculator;}public long add(long num1, long num2) {long before = System.currentTimeMillis();long result = calculator.add(num1, num2);long after = System.currentTimeMillis();System.out.println(after - before);return result;}public long subtract(long num1, long num2) {long before = System.currentTimeMillis();long result = calculator.subtract(num1, num2);long after = System.currentTimeMillis();System.out.println(after - before);return result;}}
public class CalculatorTest {public static void main(String[] args){ICalculator calculator = new Calculator();ICalculator calculatorProxy = new CalculatorProxy(calculator);calculatorProxy.add(100, 10);}}


上面我们通过代理类为Calculator增加了记录耗时的功能,但是这里我们有一个问题,在代理类中我为了记录每个方法的耗时,copy了两份几乎一模一样的方法,如果Calculator中有100个方法,那么我可能就需要copy100份一模一样的代码,这是严重违背设计原则的;不仅如此,记录耗时是一个比较通用的功能,也许我们整个项目中的所有类(委托类)都需要这个功能,我们为了让项目的所有类都可以记录方法的耗时不能不为每一个类都创建一个代理类,为每一个类的所有方法copy记录耗时的代码,太可怕了!为了解决这个问题,动态代理出现了。

2、动态代理

什么是动态代理?动态代理正如他的名字所表达的,就是动态为委托类创建代理类并生成实例。

那么怎么在程序运行中动态创建类呢?这一切都是靠java的反射机制完成的。

动态创建类需要如下个步骤:

1、拼接源码字符串;

2、调用java的编译类编译源码;

3、利用classloader把类加载到虚拟机。

动态代理就是通过反射读取委托类实现的所有接口方法,然后生成一个新的类,为每一个方法添加扩展功能代码。

实现动态代理代码比较简单,如下:

1、需要增加记录耗时的通用类

<pre name="code" class="java">public class TimeCostProxy implements InvocationHandler{Object obj;public TimeCostProxy(Object obj) {this.obj = obj;}public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {long before = System.currentTimeMillis();Object o = method.invoke(obj, args);long after = System.currentTimeMillis();long cost = after - before;System.out.println(method.getName() + "执行时间: " + cost + "ms");return o;}

}
2、执行代理

public class DynamicCalculatorTest {    public static void main( String[] args )    {     ICalculator calculator = new Calculator();    TimeCostProxy timeCostProxy = new TimeCostProxy(calculator);    ICalculator calculatorProxy = (ICalculator)Proxy.newProxyInstance(calculator.getClass().getClassLoader(), calculator.getClass().getInterfaces(), timeCostProxy);    calculatorProxy.add(100, 10);    }}

如果有兴趣可以看看动态代理的源码,还是比较容易理解的。


1 0
原创粉丝点击