从重构到模式-动态代理

曾经在一个项目中用到了Spring, 但只是涉及到了IOC,对AOP还知之甚少。现在回过头来理解下Spring的AOP概念。

从一个简单的例子看起,程序的目的是为了实现日志:

首先假定sayHello是一个业务逻辑,我们的目的就是实现记录调用sayHello的时间

public interface IHello {
    public void sayHello(String name);
}


给出一个简单的实现

public class Hello implements IHello{

    public void sayHello(String name){
        System.out.println("hello" + name);
    }
}
之后通过代理模式实现对时间的日志功能

public class HelloProxy {

    IHello hello;

    public HelloProxy(IHello hello){
        this.hello = hello;
    }

    public void sayHello(String name){
        Logger.logging("begin of calling say hello");
        hello.sayHello(name);
    }
}

public class Logger {

    public static void logging(String context) {
        System.out.println(new Date() + " " + context);
    }
}

写个测试类,看下结果

public class Main {

    public static void main(String args[]){
        HelloProxy hello = new HelloProxy(new Hello());
        hello.sayHello("Doublej");
    }
}

Tue Nov 01 21:13:40 CST 2011 begin of calling say hello
helloDoublej

上面代码,可以说是AOP最简单的实现!

如果读者再去写一个其他方法如sayGoodbye的代理,就会发现有很多的重复代码,这个时候我们就需要抽象重复代码进行重构了。

分析HelloProxy的代码

public class HelloProxy {

    //被代理对象,可用Object进行抽象
    IHello hello;

    //返回代理类实例
    public HelloProxy(IHello hello){
        this.hello = hello;
    }

    //执行被代理的方法,name为形参列表,sayHello为方法,均可被泛化
    public void sayHello(String name){
        Logger.logging("begin of calling say hello");
        hello.sayHello(name);
    }
}


我们的目的就是通过一个特殊方式来让程序自动帮我们生成代理。为了重用,我们必须进行相应的抽象,红色部分为可以被抽象的内容(重复的内容)。

一个代理需要具备以下职责:1. 包含一个被代理对象的实例 2. 执行被代理对象的方法 3.对外暴露被代理的方法

而一个动态代理就是代理的抽象。

抽象后的结果如下:

public class DynaProxy {

    private Object delegate;

    public Object getProxy(Object delegate){
        this.delegate = delegate;
        return null;//这边需要返回一个代理,可以调用jdk中的Proxy.newProxyInstance()方法.
    }


    //其中method是sayHello的抽象, args是name的抽象
    public Object invoke(Method method , Object args[])throws Throwable{
        //result是是方法返回值,即void的抽象
        Object result;

        Logger.logging("begin of calling say hello");
        result = method.invoke(delegate, args);

        return result;
    }
}

最终代码如下

public class DynaProxy implements InvocationHandler{

    private Object delegate;

    public Object getProxy(Object delegate){
        this.delegate = delegate;
        return Proxy.newProxyInstance(this.delegate.getClass().getClassLoader(),
                this.delegate.getClass().getInterfaces(), this);
    }


    public Object invoke(Object proxy ,Method method , Object args[])throws Throwable{
        Object result;

        Logger.logging("begin of calling say hello");
        result = method.invoke(delegate, args);

        return result;
    }

}

测试下

public class Main {

    public static void main(String args[]){

        IHello hello = (IHello)new DynaProxy().getProxy(new Hello());
        hello.sayHello("asad");
    }
}

Tue Nov 01 21:40:52 CST 2011 begin of calling say hello
helloasad

总结以下,刚开始理解动态代理的概念可能有点难,尤其是在看到java api中对代理的各种超长的解释之后。动态代理无非是比普通代理更加智能了点,这也就要求我们站在更抽象的视角的去看待代理这个概念,即从使用者的角度来看其对外暴露的功能。抽象也是学习oo的一个重要技能之一,oo注重于重用,重用是建立在对重复代码的不断重构的基础上的。今天也不算彻底理解了动态代理,以后再补上吧


参考资料:

http://www.blogjava.net/DoubleJ/archive/2008/03/04/183796.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值