一 動態代理主要有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之間轉換對象