框架Spring 的AOP 的实现原理是用了动态代理,今天小试一下。
先上代码:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created by Steven on 10/31/2014.
*/
interface Animal {
void info();
void run();
}
class Dog implements Animal { //实现类
public void info() {
System.out.println("一条狗");
}
public void run() {
System.out.println("飞快的跑");
}
}
class Util { // 一个通用的类 供invoke 使用
public void method1(){
System.out.println("-------before--------");
}
public void method2() {
System.out.println("------after---------");
}
}
class MyInvocationHandler implements InvocationHandler{ // 定义关联 InvocationHandler
private Object target;
public void setTarget(Object target){
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 定义需要代理执行的方法 ------ invoke方法
Util util = new Util(); // invoke 方法 实现了 在调用任何方法之前 都要 用打印 before 和after 包裹
util.method1(); // 这类似与 AOP里的 定义切点 打印 log
Object result = method.invoke(target , args);
util.method2();
return result;
}
}
class MyProxyFactory{ // 产生代理对象
public static Object getProxy(Object target){
MyInvocationHandler handler = new MyInvocationHandler();
handler.setTarget(target);
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),handler);
}
}
public class Test {
public static void main(String[] args) {
Animal target = new Dog();
Animal dog = (Animal) MyProxyFactory.getProxy(target);
dog.info(); // 想执行的是 真实的 Dog 里的 方法 其实是执行的 代理类的 Invoke 方法
dog.run();
}
}
结果控制台会输出:
-------before--------
一条狗
-------after--------
-------before--------
飞快的跑
-------after--------
从上述可以看出 动态代理 大概是什么样子的了。
所谓 动态代理 就是 代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
个人感觉就是 C 在访问 A(这里是Dog) 时 实际访问的是 B(代理后的Dog) , B 做了 A 的事 而且可以做其他的 事。C 在完成事情时却不知道是 A 还是 B 做的。
那么B 就是动态代理,A 就是委托类。
介绍到这,必须讲讲我觉得是要点的了:
方法: Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),handler);
参数:
①target.getClass().getClassLoader(); // 是获得一个来加载器,来加载代理类对象。
②target.getClass().getInterfaces(); // 是提供一组 interface 来让代理类来宣称 实现这些接口里的方法,执行代理对象的每个方法时 【都会】被代替执行handler 的 invoke 方法。
③ handler; // 是 代理对象在调用方法的时候 由 handler 关联到 InvocationHandler 上 然后执行 invoke 的方法。
好吧,到此 这些对 动态代理 的理解 应该 有些帮助了……