[ JDK生成代理 ]java
JDK中給咱們提供了一個Proxy類能夠動態的給咱們生成代理.node
假定咱們要作一個權限管理系統, 須要控制用戶對某一個方法的訪問. 若是user爲null, 那麼不讓用戶訪問save方法.框架
① 接口類: PersonService函數
public interface PersonService { public void save(); }
② 實現類: PersonServiceImpl測試
public class PersonServiceImpl implements PersonService { private String user; public PersonServiceImpl(){ } public PersonServiceImpl(String user) { this.user = user; } public void save() { System.out.println("執行了save()方法"); } public String getUser() { return user; } }
③ 生成代理類工廠: JDKProxyFactorythis
public class JDKProxyFactory implements InvocationHandler { private Object targetObject; //代理的目標對象 public Object createProxyIntance(Object targetObject) { this.targetObject = targetObject; /** * 第一個參數設置代碼使用的類裝載器,通常採用跟目標類相同的類裝載器 * 第二個參數設置代理類實現的接口 * 第三個參數設置回調對象,當代理對象的方法被調用時,會委派給該參數指定對象的invoke方法 */ return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(), this.targetObject.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { PersonServiceImpl ps = (PersonServiceImpl) this.targetObject; Object result = null; if (ps.getUser() != null) { // 若是user爲null, 則沒法調用目標方法 result = method.invoke(targetObject, args); // 把方法調用委派給目標對象 } return result; } }
④ 測試一把:代理
public class PersonServiceImplTest { @Test public void testJDKProxy() { JDKProxyFactory factory = new JDKProxyFactory(); PersonService personService = (PersonService) factory.createProxyIntance(new PersonServiceImpl("zhangsan")); personService.save(); } }
[ CGLIB生成代理 ]code
Cglib是一個優秀的動態代理框架,它的底層使用ASM在內存中動態的生成被代理類的子類。對象
使用CGLIB生成代理須要引入cglib-nodep-2.1_3.jar繼承
① CBLIG生成代理工廠: CGlibProxyFactory
public class CGlibProxyFactory implements MethodInterceptor { private Object targetObject; public Object createProxyIntance(Object targetObject) { this.targetObject = targetObject; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.targetObject.getClass()); // 設置代理類的父類 enhancer.setCallback(this); // 設置回調函數 return enhancer.create(); } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { PersonServiceImpl bean = (PersonServiceImpl) this.targetObject; Object result = null; if (bean.getUser() != null) { // 若是user爲null, 則沒法調用目標方法 result = methodProxy.invoke(targetObject, args); } return result; } }
② 測試一把
public class PersonServiceImplTest { @Test public void testCGLIBProxy() { CGlibProxyFactory factory = new CGlibProxyFactory(); PersonService personService = (PersonServiceImpl) factory.createProxyIntance(new PersonServiceImpl("lisi")); personService.save(); } }
[ 比較兩種代理 ]
1. 使用JDK的動態代理, 被代理類必定要實現了某個接口, 而使用CGLIB, 被代理類沒有實現任何接口也能夠實現動態代理功能,
2. 由於採用的是繼承, 因此cglib沒法對使用final修飾的類使用代理.
3. CGLIB的速度要遠遠快於JDK Proxy動態代理.