注:本文为阅读《疯狂Java讲义》第3版(李刚)一书后的学习笔记, 特此说明。
(关于动态代理 及 AOP的知识点,在这本书中都讲得挺好的,可以参考原书P842-848)
AOP(Aspect Orient Programming,面向切片编程),是基于动态代理实现的。能够让多个代码块可以执行相同的代码段,又无须在程序中已硬编码的方式直接调用这些相同的代码段。
下面通过一个例子来说明AOP的过程(该例子来自原书):
接口:
public interface Dog
{
// info方法声明
void info();
// run方法声明
void run();
}
目标对象(被代理对象):
public class GunDog implements Dog
{
// 实现info()方法,仅仅打印一个字符串
public void info()
{
System.out.println("我是一只猎狗");
}
// 实现run()方法,仅仅打印一个字符串
public void run()
{
System.out.println("我奔跑迅速");
}
}
“插入”的方法
public class DogUtil
{
// 第一个拦截器方法
public void method1()
{
System.out.println("=====模拟第一个通用方法=====");
}
// 第二个拦截器方法
public void method2()
{
System.out.println("=====模拟通用方法二=====");
}
}
InvocationHandler实现类,这是实现AOP编程的关键。该实现类的invoke()方法将会作为代理对象的方法实现。该invoke()方法中包含了一行关键的代码,这行代码通过反射以目标对象作为主调来执行method方法,也就是回调了目标对象的原有方法。
public class MyInvokationHandler implements InvocationHandler
{
// 需要被代理的对象
private Object target;
public void setTarget(Object target)
{
this.target = target;
}
// 执行动态代理对象的所有方法时,都会被替换成执行如下的invoke方法
public Object invoke(Object proxy, Method method, Object[] args)
throws Exception
{
DogUtil du = new DogUtil();
// 执行DogUtil对象中的method1。
du.method1();
// 以target作为主调来执行method方法
Object result = method.invoke(target , args);
// 执行DogUtil对象中的method2。
du.method2();
return result;
}
}
生成代理实例:
public class MyProxyFactory
{
// 为指定target生成动态代理对象
public static Object getProxy(Object target)
throws Exception
{
// 创建一个MyInvokationHandler对象
MyInvokationHandler handler =
new MyInvokationHandler();
// 为MyInvokationHandler设置target对象
handler.setTarget(target);
// 创建、并返回一个动态代理
return Proxy.newProxyInstance(target.getClass().getClassLoader()
, target.getClass().getInterfaces() , handler);
}
}
主程序:
public class Test
{
public static void main(String[] args)
throws Exception
{
// 创建一个原始的GunDog对象,作为target
Dog target = new GunDog();
// 以指定的target来创建动态代理
Dog dog = (Dog)MyProxyFactory.getProxy(target);
dog.info();
dog.run();
}
}
运行结果:
可以看到,在执行动态代理对象dog的info()和run()方法时,会在前后分别加上DogUtil的method1()和method2()。这也就是面向切片编程(AOP)。