一 动态代理主要有java自带的代理和cglib方式实现的代理
首先讲下java自带的代理
public interface Hello {
void sayHello();
}
public class HelloImpl implements Hello {
@Override
public void sayHello() {
System.out.println("hello");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxy implements InvocationHandler {
private Object targetObject;
public void before() {
System.out.println("before");
}
public void after() {
System.out.println("after");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(targetObject, args);
after();
return result;
}
public Object getProxy(Object targetObject) {
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this);
}
}
------------------然后是cglib自带的代理-------------------------
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxy implements MethodInterceptor {
public void before() {
System.out.println("before");
}
public void after() {
System.out.println("after");
}
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
before();
Object result = methodProxy.invokeSuper(object, args);
after();
return result;
}
public <T> T getProxy(Class<T> cls) {
return (T) Enhancer.create(cls, this);
}
}
测试类:
public class Client {
public static void main(String[] args) {
Hello hello = (Hello) new JdkProxy().getProxy(new HelloImpl());
hello.sayHello();
CglibProxy cglibProxy = new CglibProxy();
cglibProxy.getProxy(HelloImpl.class).sayHello();
}
}
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。被代理的对象必须要实现接口
而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。因为采用的是继承,所以不能对final修饰的类进行代理
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换