曾经在一个项目中用到了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