一 动态代理主要有java自带的代理和cglib方式实现的代理java
首先讲下java自带的代理spring
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自带的代理-------------------------ide
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来处理。被代理的对象必需要实现接口this
而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,经过修改其字节码生成子类来处理。由于采用的是继承,因此不能对final修饰的类进行代理代理
一、若是目标对象实现了接口,默认状况下会采用JDK的动态代理实现AOP
二、若是目标对象实现了接口,能够强制使用CGLIB实现AOP code
三、若是目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换对象