Aop
簡介:
Aop(Aspect Oriented Programming)面向切面編程,是OOP面向對象編程的一種補充將程序中交叉業務(事務,日誌)代碼提取出來,封裝成切面,由AOP容器在適當時機位置將封裝成的切面動態的織入到具體業務邏輯中。
AOP不是spring特有的。
應用場合:適用於具有橫切邏輯的場合,如事務管理,日誌記錄,性能檢測,異常通知,訪問控制等。
作用:
不改變原有代碼的基礎動態添加新的功能。
模塊化。
術語:
連接點(JoinPoint):程序執行的某個特定位置,如方法調用前,方法調用後,方法拋出異常時,方法調用前後等。
切入點(PointCut):定位位置找到需要切入的連接點,即切點。
增強Advice也稱爲通知: 在切點上執行的一段代碼用來實現某些功能。
目標對象 Target :將執行增強處理的目標類。
織入(Weaving) :將增強添加到目標類具體切入點的過程。
代理(Proxy) :一個類被織入增強後,會產生一個代理類。
切面 Aspect :切點和增強的組合。
引介 Introduction 也稱爲引入。
實現原理
代理模式:
概念:爲其他對象提供一種代理,以控制對這個對象的訪問,起到中介的作用,通過代理對象訪問目標對象,可以增強額外的操作,擴展目標對象的功能。
分類:
靜態代理:代理類是程序員創建或工具生成的,所謂靜態代理就是程序運行之前就已經存在代理類的字節碼文件。缺點:代理對象需要和目標對象實現相同的接口,如果接口增加方法,目標對象和代理對象都要維護。
動態代理:代理類是程序在運行期間由JVM根據反射等機制動態生成的,自動生成代理類和代理對象,所謂動態就是在程序運行之前不存在代理類的字節碼文件。
代理三要素:
一:實現目標類的接口。
二:初始化目標類的實例。
三:交叉業務,要執行的操作。
動態代理:
JDK技術:
proxy.newProxyInstance(
classloader 目標類的類加載器
interfaces 目標類得到接口列表
InvocationHandler 交叉業務邏輯
)
缺點:目標對象必須實現一個或多個接口,如果沒有實現接口,則無法使用JDK的動態代理,此時可以使用cglib技術
代碼
書寫UserService接口
package springaop01.service;
/**
* package_name:springaop01.service
*
* author:徐亞遠 Date:2020/2/18 18:29
* 項目名:springDemo01
* Description:
**/
public interface UserService {
/**
* @Author : 徐亞遠
* @Date : 2020/2/18 20:34
* @param username
* @param password
* @Description :
*/
void login(String username, String password);
}
書寫UserService的實現類UserServiceImpl
package springaop01.service.impl;
import springaop01.service.UserService;
/**
* package_name:springaop01.service.impl
* Author:徐亞遠
* Date:2020/2/18 18:29
* 項目名:springDemo01
* Desription:
**/
public class UserServlceImpl implements UserService {
/**
* @param password
* @param username
* @Author : 徐亞遠
* @Date : 2020/2/18 21:03
* @Description :
*/
@Override
public void login(String username, String password) {
System.out.println("loginUserServiceImpl登錄:" + username + " " + password);
}
}
書寫測試類使用jdk動態代理技術
package springaop01.controller;
import springaop01.service.UserService;
import springaop01.service.impl.UserServlceImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
/**
* package_name:springaop01.controller
* @author:徐亞遠
* Date:2020/2/18 18:41
* 項目名:springDemo01
* Description:
**/
public class UserController {
public static void main(String[] args) {
/** 動態代理*/
UserService userService = (UserService) Proxy.newProxyInstance(
//目標類的類加載器
UserServlceImpl.class.getClassLoader(),
//目標類的接口
new Class[]{UserService.class},
//交叉業務
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("打印日誌:" + method.getName() + " start at: [" + System.currentTimeMillis()
+"]"+" "+"args:"+Arrays.toString(args));
Object object = method.invoke(new UserServlceImpl(), args);
return object;
}
}
);
userService.login("admin", "admin");
}
}
實現結果如圖: