基于JDK的动态代理
基于jdk的动态代理,底层是依赖java反射来实现增强逻辑织入到业务逻辑里面的。Spring AOP在目标累实现接口的情况下,默认采用JDK的动态代理方式进行目标类的代理。下面来看看JDK动态代理的原理:
我们的目标类是Person,他实现了接口Voice,然后我们实现一个MyHandler,MyHandler持有Person,在调用invok的时候,利用反射机制先判断调用的方法是不是say,如果是,在方法请后织入增强逻辑。
public interface Voice {
void say();
}
public class Person implements Voice {
String name;
public Person(String name) {
this.name = name;
}
public void say() {
System.out.println(name + " is saying hello!");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyHandler implements InvocationHandler {
private Object object;
public MyHandler(Object object) {
this.object = object;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object res = null;
if (method.getName().equals("say")) {
System.out.println("before call say method");
res = method.invoke(object, args);
System.out.println("after call say method");
}
return res;
}
}
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
Person p =new Person("cy");
Voice v = (Voice) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{Voice.class}, new MyHandler(p));
v.say();
}
}
xxxbefore call say method
cy is saying hello!
after call say method
Process finished with exit code 0
基于CGLIB的动态代理
基于CGLIB的动态代理,底层是利用ASM技术实现的,ASM动态生成目标类的子类的字节码。在子类中,将增强逻辑织入进去,父类负责业务逻辑,子类负责增强逻辑。由于需要继承,目标类不可以是final声明的类。
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class MyMethodInterceptor implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object res = null;
if (method.getName().equals("say")) {
System.out.println("before say hello!");
res = methodProxy.invokeSuper(o, objects);
System.out.println("after say hello!");
}
return res;
}
}
import net.sf.cglib.proxy.Enhancer;
public class Main {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Dog.class);
enhancer.setCallback(new MyMethodInterceptor());
Dog dog = (Dog)enhancer.create();
dog.say();
}
}
before say hello!
the dog is saying hello!
after say hello!
Process finished with exit code 0
两种动态代理技术的对比
JDK动态代理 | 基于CGLIB的动态代理 | |
---|---|---|
生成速度 | 较快 | 较慢,可以使用缓存技术解决这个问题 |
执行速度 | 较慢 | 较快 |
目标类是否需要实现接口 | 需要 | 不需要 |
目标类是否可以声明为final | 可以 | 不可以 |