1 編程范式
1.1 面向過程
1.2 面向對象
1.3 面向切面編程
1.4 函數式編程
1.5 事件驅動編程
2 什么是面向切面編程
2.1 是一種編程范式,而不是一種編程語言
2.2 解決一些特定的問題
2.3 作為面向對象編程的一種補充
3 AOP產生的初衷
3.1 解決代碼重復性問題 Don't Repeat Yourself
3.2 解決關注點分離問題 Separation of Concerns
3.2.1 水平分離(技術上划分)
控制層 -> 服務層 -> 持久層
3.2.2 垂直分離(模塊上划分)
模塊划分
3.2.3 切面分離(功能上划分)
分離功能性需求和非功能性需求
4 使用AOP的好處
4.1 集中處理某一個關注點、橫切邏輯
4.2 可以很方便地添加、刪除關注點
4.3 侵入性減少,增強代碼可讀性和可維護性
5 AOP的使用場景
5.1 權限控制
5.2 緩存控制
5.3 事物控制
5.4 審計日志
5.5 性能監控
5.6 分布式追蹤
5.7 異常處理
6 利用傳統方法實現權限驗證
6.1 創建一個springBoot項目
下載地址:點擊前往
6.2 新建一個Product實體類
Product.java
6.3 新建一個權限模擬類
該類主要用來設定用戶和獲取用戶
package cn.test.demo.base_demo.security;
/**
* @author 王楊帥
* @create 2018-04-29 17:15
* @desc 模擬用戶登錄,該類可以設定用戶和獲取用戶
**/
public class CurrentSetHolder {
private final static ThreadLocal<String> holder = new ThreadLocal<>();
/**
* 獲取用戶
* @return
*/
public static String get() {
return holder.get() == null ? "unknown" : holder.get();
}
/**
* 設定用戶
* @param user
*/
public static void set(String user) {
holder.set(user);
}
}
6.4 新建一個權限校驗類
該類主要用於判斷當前用戶是否是“admin”用戶
package cn.test.demo.base_demo.service;
import cn.test.demo.base_demo.security.CurrentSetHolder;
import org.springframework.stereotype.Component;
/**
* @author 王楊帥
* @create 2018-04-29 17:19
* @desc 權限校驗服務類
**/
@Component
public class AuthService {
/**
* 權限檢查,如果用戶不是 “admin" 就會報錯
*/
public void checkAccess() {
String user = CurrentSetHolder.get();
if (!"admin".equals(user)) {
throw new RuntimeException("operation not allow.");
}
}
}
6.5 新建ProductService類
該類主要實現對Product的一些操作
ProductService.java
6.6 創建一個服務層測試類
在調用ProductService的insert方法前對用戶進行設定
ProductServiceTest.java
7 利用AOP實現權限驗證
7.1 新建一個springBoot項目
下載地址:點擊前往
7.2 創建一個Product實體類
package cn.test.demo.base_demo.entity;
/**
* @author 王楊帥
* @create 2018-04-29 17:11
* @desc 商品實體類
**/
public class Product {
private Integer id;
private String name;
public Product() {
}
public Product(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Product{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
7.3 創建一個AdminOnly注解
package cn.test.demo.base_demo.security;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AdminOnly {
}
7.4 新建一個權限模擬類
該類主要用來設置用戶和獲取用戶
package cn.test.demo.base_demo.security;
/**
* @author 王楊帥
* @create 2018-04-29 17:15
* @desc 模擬用戶登錄,該類可以設定用戶和獲取用戶
**/
public class CurrentSetHolder {
private final static ThreadLocal<String> holder = new ThreadLocal<>();
/**
* 獲取用戶
* @return
*/
public static String get() {
return holder.get() == null ? "unknown" : holder.get();
}
/**
* 設定用戶
* @param user
*/
public static void set(String user) {
holder.set(user);
}
}
7.5 創建一個切面類
該類主要對所有使用了@AdminOnly注解的方法進行權限校驗
package cn.test.demo.base_demo.security;
import cn.test.demo.base_demo.service.AuthService;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author 王楊帥
* @create 2018-04-29 17:37
* @desc 權限檢查的AOP類
**/
@Aspect
@Component
public class SecurityAspect {
@Autowired
AuthService authService;
@Pointcut("@annotation(AdminOnly)")
public void adminOnly(){
}
@Before("adminOnly()")
public void check(){
authService.checkAccess();
}
}
7.6 新建一個ProductService服務類
該類的delete方法用了@AdminOnly注解,所以delete方法會進行權限校驗
ProductService.java
7.7 創建一個測試類
productService.delete(id) 方法中有權限驗證,如果不是“admin"用戶就會報錯【利用AOP實現的】
ProductServiceTest.java

