如何理解 Spring 中的 AOP
1、AOP 的概述java
Spring 中的 AOP 實現原理編程
a、接口 + 實現類 :Spring採用 jdk 的 動態代理Proxy。b、實現類:Spring 採用 cglib字節碼加強。緩存
a、Aop底層將採用代理機制進行實現(最底層也是依賴反射)。安全
2、AOP 實現案例框架
一、對 AOP 的理解(畫圖解釋)
二、AOP 中經過 JDK動態代理簡單案例演示
接口、實現類和切面類ide
public interface UserService { void addUser(); void updateUser(); int deleteUser(int id); } ========================================================================================= public class UserServiceImpl implements UserService { @Override public void addUser() { System.out.println("添加用戶"); } @Override public void updateUser() { System.out.println("更新用戶"); } @Override public int deleteUser(int id) { System.out.println("經過id刪除用戶"); return 1; } } 切面類 public class MyAspect { public void before(){ System.out.println("開啓事務"); } public void after(){ System.out.println("提交事務"); } }
JDK實現動態代理函數式編程
public class MyBeanFactory { // JDK實現動態代理 public static UserService createUserService() { //1.建立目標對象target final UserService userService = new UserServiceImpl(); //2.聲明切面類對象 final MyAspect aspect = new MyAspect(); //3.把切面類2個方法應用於目標類 //3.1 建立JDK代理,攔截方法 UserService serviceProxy = (UserService) Proxy.newProxyInstance( MyBeanFactory.class.getClassLoader(), userService.getClass().getInterfaces(), (proxy, method, args) -> { //開啓事務 aspect.before(); //方法返回值:業務方法的返回值 Object retObj = method.invoke(userService, args); //System.out.println("攔截返回值:" + retObj); //提交事務 aspect.after(); return retObj; } ); return serviceProxy; } }
測試函數函數
public class AOPTest { public static void main(String[] args) { UserService userService = MyBeanFactory.createUserService(); userService.deleteUser(1); userService.addUser(); userService.updateUser(); } }
測試結果以下所示:性能
開啓事務 經過id刪除用戶 提交事務 <=====================> 開啓事務 添加用戶 提交事務 <=====================> 開啓事務 更新用戶 提交事務 <=====================>
從測試結果能夠看出,每次在執行業務代碼的時候,會攔截對應的方法,執行切面類。
重點:JDK 的動態代理是經過接口和實現類完成的。測試
在 debug 測試函數: UserService userService = MyBeanFactory.createUserService();
能夠看出直接獲得的是代理對象,代理對象中就有實現的功能。
在 debug 測試函數:UserService userService = new UserServiceImpl();
能夠看出直接獲得的是其實現類,沒有代理。
感興趣的同窗能夠將測試函數中代碼替換成上面兩種。看看測試結果,以便於更好理解 AOP 思想。
三、AOP 中經過 CGlib 動態代理簡單案例演示
public class StudentService { void delete() { System.out.println("刪除用戶"); } void add() { System.out.println("添加用戶"); } void update() { System.out.println("更新用戶"); } }
public class MyBeanFactory { // CGlib實現代理 public static StudentService createStudentService(){ //1.建立目標對象target final StudentService studentService = new StudentService(); //2.聲明切面類對象 final MyAspect aspect = new MyAspect(); //3.建立加強對象 Enhancer enhancer = new Enhancer(); //設置父類 enhancer.setSuperclass(studentService.getClass()); //設置回調【攔截】 enhancer.setCallback((MethodInterceptor) (proxy, method, args, methodProxy) -> { aspect.before(); Object retObj = methodProxy.invokeSuper(proxy,args);//解藕 System.out.println("攔截....."); aspect.after(); return retObj; }); //建立代理對象 StudentService serviceProxy = (StudentService) enhancer.create(); //System.out.println("serviceProxy); return serviceProxy; } }
測試函數
public class AOPTest { public static void main(String[] args) { StudentService studentService = MyBeanFactory.createStudentService(); studentService.add(); System.out.println("<=====================>"); studentService.delete(); System.out.println("<=====================>"); studentService.update(); System.out.println("<=====================>"); } }
測試結果以下所示:
開啓事務 添加用戶 攔截..... 提交事務 <=====================> 開啓事務 刪除用戶 攔截..... 提交事務 <=====================> 開啓事務 更新用戶 攔截..... 提交事務 <=====================>
CGlib 代理重點總結
a、沒有接口,只有實現類。 b、採用字節碼加強框架 cglib,在運行時 建立目標類的子類,從而對目標類進行加強。