在學習spring的過程當中,瞭解到一個很重要的java編程思想,就是面向切面的編程(aop)。什麼是面向切面的編程呢?對於這個概念我在網上查了,獲得以下的答案:
java
AOP(Aspect-Oriented Programming,面向切面的編程),它是能夠經過預編譯方式和運行期動態代理實現在不修改源代碼的狀況下給程序動態統一添加功能的一種技術。它是一種新的方法論,它是對傳統OOP編程的一種補充。spring
概念性的東西比較死,關鍵是要理解其中的原理。看下圖所示:數據庫
當你有一個寫好的方法,想要在其調用的前面或者後面加上一些記錄日誌或別的一些邏輯,但又不想更改(或者不能改)原有的代碼時,AOP就能發揮它極大的優點了。接下來看看使用Proxy和 InvocationHandler是如何實現的。編程
public interface UserDao { public void save(User user) ; } //定義一個保存User對象到數據庫的接口
public class UserDaoImpl implements UserDao { @Override public void save(User user) { System.out.println("user saved!"); } } //接口的實現
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; //編寫切面邏輯類,必需要實現InvocationHandler 接口 public class DebugInterceptor implements InvocationHandler { private Object target; public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } //須要插入的邏輯 private void before(Method m) { System.out.println(m.getName() + " start!"); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(method); method.invoke(target, args);//使用java反射調用代理方法 return null; } }
使用Junit4寫了個單元測試,測試代理方法。調用Proxy類的靜態方法newProxyInstance(classloader,interfaces,handler)產生代理對象。代理對象與被代理對象實現了同一個接口UserDao,因此能調用其中的save方法。框架
public class ProxyTest { @Test public void testProxy() { UserDao userDao = new UserDaoImpl(); DebugInterceptor di = new DebugInterceptor(); di.setTarget(userDao); UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), di); userDaoProxy.save(new User()); } }
測試結果 ide
save start!性能
user saved!單元測試
成功將切面邏輯加入到方法調用以前,嘿嘿。
學習
到此,Proxy與InvocationHandler實現動態代理的實現過程就搞定了。java動態代理不僅有這一個方法,還能用CGlib,CGlib是一個強大的,高性能,高質量的代碼生成類庫,這裏就很少作介紹了,你們能夠到網上本身查。測試
還有spring的AOP實現的動態代理不僅是這樣子,它使用aspectJ這個切面框架。具體的等之後再繼續說吧。繼續研究。。。
最後,發現本身寫得好少,也存在不少不足,歡迎你們指點與吐槽。
在交流中成長。