漫畫 | Spring AOP
上期,我們看到有小夥伴留言說希望講講AOP
然後......
別激動,來得及
什麼是AOP
AOP是Spring 框架的一個關鍵元件,全稱為Aspect-OrientedProgramming(面向切面程式設計),目前已是一種比較成熟的程式設計方式。
AOP採取橫向抽取機制,將分散在各個方法中的重複程式碼提取出來,然後在編譯或執行的時候,再將這些程式碼應用到需要執行的地方。
注:提取出來的程式碼應用到需要執行的地方,並不會把原始碼加到需要的地方執行,即原始碼檔案不會更改,但是它會影響最終的機器編譯程式碼
意思就是,有一些通用功能的程式碼可以提取出來,然後在使用的時候應用進去就可以了,比如表單驗證和日誌記錄等等
AOP術語
Aspect(切面)
通常指封裝起來用於插入到指定位置實現某項功能的類
Join point(連線點)
在SpringAOP中,連線點指方法的呼叫
Pointcut(切入點)
切面與程式流程的交叉點,即那些需要處理的連線點,通常在程式中,切入點指的是類或者方法名
Advice(通知/增強處理)
就是程式實際執行之前或之後執行的方法,也就是AOP加入的程式碼
Target Object(目標物件)
即需要加入AOP程式碼的物件
Proxy(代理)
AOP框架動態生成的一個物件,該物件可以作為目標物件使用
Weaving(織入)
把切面連線到其它的應用程式型別或者物件上,並建立一個需要Advice物件的過程
看不懂就先往下看,關於術語等自己會了,自然就好理解多了
這時......
阿音過來知道了小知在學AOP
於是......
阿音非要展示一個關於AOP的小例子
UserDao介面
package com.aop.jdk; public interface UserDao { public void addUser(); }
UserDaoImpl
package com.aop.jdk; public class UserDaoImpl implements UserDao { @Override public void addUser() { System.out.println("新增使用者"); } }
JdkProxy
package com.aop.jdk; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import com.aop.aspect.MyAspect; /** * JDK代理類 */ public class JdkProxy implements InvocationHandler{ // 宣告目標類介面 private UserDao userDao; // 建立代理方法 publicObject createProxy(UserDao userDao) { this.userDao = userDao; // 1.類載入器 ClassLoader classLoader = JdkProxy.class.getClassLoader(); // 2.被代理物件實現的所有介面 @SuppressWarnings("rawtypes") Class[] clazz = userDao.getClass().getInterfaces(); // 3.使用代理類,進行增強,返回的是代理後的物件 returnProxy.newProxyInstance(classLoader,clazz,this); } /* * 所有動態代理類的方法呼叫,都會交由invoke()方法去處理 * proxy 被代理後的物件 * method 將要執行的方法 * args 執行方法時需要的引數 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 宣告切面 MyAspect myAspect = new MyAspect(); // 指定位置程式執行前執行這個方法 myAspect.start(); // 在目標類上呼叫方法 Object obj = method.invoke(userDao, args); // 指定位置程式執行結束後執行 myAspect.end(); return obj; } }
MyAspect
package com.aop.aspect; /** *切面 */ public class MyAspect { public void start(){ System.out.println("模擬事務處理功能 ..."); } public void end(){ System.out.println("程式結束後執行此處 ..."); } }
JdkTest
測試結果專案編寫完之後執行該類
package com.aop.test; import com.aop.jdk.JdkProxy; import com.aop.jdk.UserDao; import com.aop.jdk.UserDaoImpl; public class JdkTest { public static void main(String[] args) { // 建立代理物件 JdkProxy jdkProxy = new JdkProxy(); // 建立目標物件 UserDao userDao= new UserDaoImpl(); // 從代理物件中獲取增強後的目標物件 UserDao userDao1 = (UserDao) jdkProxy.createProxy(userDao); // 執行方法 userDao1.addUser(); } }
執行之後,我們可以看到以下結果:
我們可以看到,在我們執行新增使用者的方法時,依據我們AOP程式設計,系統自動執行了start方法和end方法
在實際運用中,我們可以把一些通用的方法放到start和end的位置,在需要的方法處加入切面即可
此外,建議大家再瞭解下AspectJ
AspectJ實現AOP有兩種方式:一種是基於XML的宣告式,另一種是基於註解的宣告式
基於XML的宣告式AspectJ要便捷一些,但是存在配置資訊多的缺點
基於註解的宣告式AspectJ則通過註解的方式減少了很多配置資訊