經過代理控制對象的訪問,能夠詳細訪問某個對象的方法,在這個方法調用處理,或調用後處理。既(AOP微實現) ,AOP核心技術面向切面編程。 java
SpringAOP、事物原理、日誌打印、權限控制、遠程調用、安全代理 能夠隱蔽真實角色程序員
由程序員建立或工具生成代理類的源碼,再編譯代理類。所謂靜態也就是在程序運行前就已經存在代理類的字節碼文件,代理類和委託類的關係在運行前就肯定了。spring
public interface IUserDao { void save(); } public class UserDao implements IUserDao { public void save() { System.out.println("已經保存數據..."); } }
代理類編程
public class UserDaoProxy implements IUserDao { private IUserDao target; public UserDaoProxy(IUserDao iuserDao) { this.target = iuserDao; } public void save() { System.out.println("開啓事物..."); target.save(); System.out.println("關閉事物..."); } }
是根據類加載器和接口建立代理類(此代理類是接口的實現類,因此必須使用接口 面向接口生成代理,位於java.lang.reflect包下)安全
缺點:jdk動態代理,必須是面向接口,目標業務類必須實現接口框架
// 每次生成動態代理類對象時,實現了InvocationHandler接口的調用處理器對象 public class InvocationHandlerImpl implements InvocationHandler { private Object target;// 這其實業務實現類對象,用來調用具體的業務方法 // 經過構造函數傳入目標對象 public InvocationHandlerImpl(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; System.out.println("調用開始處理"); result = method.invoke(target, args); System.out.println("調用結束處理"); return result; } public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { // 被代理對象 IUserDao userDao = new UserDao(); InvocationHandlerImpl invocationHandlerImpl = new InvocationHandlerImpl(userDao); ClassLoader loader = userDao.getClass().getClassLoader(); Class<?>[] interfaces = userDao.getClass().getInterfaces(); // 主要裝載器、一組接口及調用處理動態代理實例 IUserDao newProxyInstance = (IUserDao) Proxy.newProxyInstance(loader, interfaces, invocationHandlerImpl); newProxyInstance.save(); } }
原理:利用asm開源包,對代理對象類的class文件加載進來,經過修改其字節碼生成子類來處理。 函數
使用cglib[Code Generation Library]實現動態代理,並不要求委託類必須實現接口,底層採用asm字節碼生成框架生成代理類的字節碼工具
public class CglibProxy implements MethodInterceptor { private Object targetObject; // 這裏的目標類型爲Object,則能夠接受任意一種參數做爲被代理類,實現了動態代理 public Object getInstance(Object target) { // 設置須要建立子類的類 this.targetObject = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(this); return enhancer.create(); } public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("開啓事物"); Object result = proxy.invoke(targetObject, args); System.out.println("關閉事物"); // 返回代理對象 return result; } public static void main(String[] args) { CglibProxy cglibProxy = new CglibProxy(); UserDao userDao = (UserDao) cglibProxy.getInstance(new UserDao()); userDao.save(); } }
Spring中。this
JDK動態代理只能對實現了接口的類生成代理,而不能針對類 。代理
CGLIB是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法 。
由於是繼承,因此該類或方法最好不要聲明成final ,final能夠阻止繼承和多態。
我的博客 蝸牛