要理解方法拦截,先要理解java的动态Proxy在Spring中,被拦截方法的类,都不是直接new出来,而是配置在Spring的工厂中,由Spring负责创建的。例如我们程序需要一个Coupe类的instance,Spring返回给我们程序的实际不是Coupe,而是Coupe的proxy,接下来调用Coupe的方法其实都是通过proxy进行的,自然就可以在proxy中拦截Coupe的所有方法了下面是使用java dynamic proxy的使用方法,当然,Spring不是这么做的,而是使用CGLIB和ASM来动态的生成proxy的。如果大家有兴趣,可以另开话题讨论。package com.skykiller.dyproxy;import java.lang.reflect.*;
import java.io.PrintWriter;public class TracingHandler implements InvocationHandler { private Object target;
private PrintWriter out;
public TracingHandler(Object target, PrintWriter out) {
this.target = target;
this.out = out;
} public static Object createProxy(Object obj, PrintWriter out) {
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new TracingHandler(obj,out) );
} public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
out.println( method.getName() + " called.");
try {
result = method.invoke( target, args);
} catch (InvocationTargetException e) {
out.println( method.getName() + " throw "+e.getCause());
throw e.getCause();
}
out.println(method.getName() + " return");
out.flush();
return result;
}
}
package com.skykiller.dyproxy;public interface Car { void init(String name, int passengers); void show();}package com.skykiller.dyproxy;public class Coupe implements Car { private String name;
private int passengers; public void init(String name, int passengers) {
this.name = name;
this.passengers = passengers;
}
public String toString() {
return name + " is a " + passengers + " seats car.";
} public void show() {
System.out.println(toString());
}
/**
* @param args
*/
public static void main(String[] args) {
CarFactory coupeFactory = new CarFactory("com.skykiller.dyproxy.Coupe",true);
Car coupe = coupeFactory.newInstance("my coupe", 2);
System.out.println("Class name:"+coupe.getClass().getName());
System.out.println("My coupe's info:"+coupe);
coupe.show();
}}
import java.io.PrintWriter;public class TracingHandler implements InvocationHandler { private Object target;
private PrintWriter out;
public TracingHandler(Object target, PrintWriter out) {
this.target = target;
this.out = out;
} public static Object createProxy(Object obj, PrintWriter out) {
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new TracingHandler(obj,out) );
} public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
out.println( method.getName() + " called.");
try {
result = method.invoke( target, args);
} catch (InvocationTargetException e) {
out.println( method.getName() + " throw "+e.getCause());
throw e.getCause();
}
out.println(method.getName() + " return");
out.flush();
return result;
}
}
package com.skykiller.dyproxy;public interface Car { void init(String name, int passengers); void show();}package com.skykiller.dyproxy;public class Coupe implements Car { private String name;
private int passengers; public void init(String name, int passengers) {
this.name = name;
this.passengers = passengers;
}
public String toString() {
return name + " is a " + passengers + " seats car.";
} public void show() {
System.out.println(toString());
}
/**
* @param args
*/
public static void main(String[] args) {
CarFactory coupeFactory = new CarFactory("com.skykiller.dyproxy.Coupe",true);
Car coupe = coupeFactory.newInstance("my coupe", 2);
System.out.println("Class name:"+coupe.getClass().getName());
System.out.println("My coupe's info:"+coupe);
coupe.show();
}}
然后在调用的实际上是子类的方法
在子类方法中加入需要的代码
然后再调用超类的方法
这就是所谓的方法拦截用cglib的好处在与 他可以生成类的子类 拦截所有超类的方法
而jdk的代理类需要接口 只能拦截接口中的方法
例子比较简单,你可以参看spring参考手册第6章:
http://www.redsaga.com/spring_ref/2.0/html/aop.html#aop-introduction-defn