欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot整合Aop全過程

 更新時間:2024年10月17日 17:06:23   作者:小疙瘩的編程之路  
AOP(面向切面編程)技術(shù)可以高效地解決日志記錄、事務(wù)管理、權(quán)限控制等問題,日志記錄通過自定義注解和切面類,自動記錄方法調(diào)用詳情,減少重復(fù)代碼,事務(wù)管理方面,通過AOP可以在不改變業(yè)務(wù)代碼的情況下,實(shí)現(xiàn)事務(wù)的自動開啟、提交和回滾,保證數(shù)據(jù)一致性

AOP 可以做什么?

  • 1. 日志記錄
  • 自動記錄方法的調(diào)用、參數(shù)、返回值和異常等信息,減少了在每個方法中添加日志代碼的需要。
  • 2. 管理事務(wù)
  • 在方法執(zhí)行前后自動處理事務(wù)的開啟、提交和回滾,確保數(shù)據(jù)的一致性和完整性。
  • 3. 權(quán)限控制
  • 實(shí)現(xiàn)方法的訪問控制,檢查用戶權(quán)限,確保只有授權(quán)用戶才能執(zhí)行特定操作。
  • 4. 性能監(jiān)控
  • 自動收集方法的執(zhí)行時間、調(diào)用次數(shù)等性能指標(biāo),幫助開發(fā)者進(jìn)行性能分析和優(yōu)化。
  • 5. 緩存管理
  • 實(shí)現(xiàn)方法結(jié)果的緩存,減少重復(fù)計(jì)算,提高系統(tǒng)性能。
  • 6. 異常處理
  • 統(tǒng)一處理方法執(zhí)行中的異常,簡化異常捕獲和處理邏輯。
  • 7. 輸入驗(yàn)證
  • 在方法執(zhí)行前對輸入?yún)?shù)進(jìn)行驗(yàn)證,保證數(shù)據(jù)的有效性和完整性。
  • 8. 動態(tài)代理
  • 創(chuàng)建代理對象,在不修改原有類的情況下添加額外的行為。

應(yīng)用場景

  • Web開發(fā):用于請求處理、事務(wù)管理、安全控制等。
  • 企業(yè)應(yīng)用:在服務(wù)層實(shí)現(xiàn)統(tǒng)一的日志和異常處理。
  • 微服務(wù):在服務(wù)之間進(jìn)行統(tǒng)一的監(jiān)控和熔斷處理。

日志記錄

1.準(zhǔn)備工作

首先需要導(dǎo)入AOP依賴

pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.50</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

然后需要創(chuàng)建日志記錄數(shù)據(jù)庫和實(shí)體類還有在Mapper層實(shí)現(xiàn)插入數(shù)據(jù)方法

  • 實(shí)體類
//操作日志實(shí)體類
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OperateLog {
    private Integer id; //主鍵ID
    private Integer operateUser; //操作人ID
    private LocalDateTime operateTime; //操作時間
    private String className; //操作類名
    private String methodName; //操作方法名
    private String methodParams; //操作方法參數(shù)
    private String returnValue; //操作方法返回值
    private Long costTime; //操作耗時
}
  • Mapper接口
@Mapper
public interface OperateLogMapper {

    //插入日志數(shù)據(jù)
    @Insert("insert into operate_log (operate_user, operate_time, class_name, method_name, method_params, return_value, cost_time) " +
            "values (#{operateUser}, #{operateTime}, #{className}, #{methodName}, #{methodParams}, #{returnValue}, #{costTime});")
    public void insert(OperateLog log);

}

2.創(chuàng)建自定義注解和切面類

因?yàn)槲覀円涗浀牟僮魅罩臼菍τ跀?shù)據(jù)的增,刪,改所以采用@annotation來指定要為連接點(diǎn)的方法。

而且在涉及到消耗時間的字段,所以需要采用@Around通知類型

  • 自定義注解類
@Retention(RetentionPolicy.RUNTIME)//運(yùn)行時有效
@Target(ElementType.METHOD)//作用在方法上
public @interface Log {
}

3.實(shí)現(xiàn)日志記錄(Around)

首先需要需要記錄的操作接口方法前加上@Log注解

接下來在切面類中實(shí)現(xiàn)操作日志記錄:

@Aspect
@Component
public class LogAsper {
    @Autowired
    private OperateLogMapper operateLogMapper;
    @Autowired
    private HttpServletRequest request;

    @Around("@annotation(com.ly.springbootdemotlias.anno.Log)")//匹配加了Log注解的方法
    public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
        OperateLog operateLog = new OperateLog();
        //獲取操作人id,通過獲取并解析jwt令牌
        String jwt = request.getHeader("token");
        Claims claims = JwtUtils.parseJwt((jwt));
        Integer operateUser =(Integer) claims.get("id");
        operateLog.setOperateUser(operateUser);
        //獲取操作時間
        operateLog.setOperateTime(LocalDateTime.now());
        //獲取操作類名
        operateLog.setClassName(joinPoint.getTarget().getClass().getName());
        //獲取操作方法名
        operateLog.setMethodName(joinPoint.getSignature().getName());
        //獲取操作方法參數(shù)
        operateLog.setMethodParams(Arrays.toString(joinPoint.getArgs()));
        //獲取開始時間
        long begin = System.currentTimeMillis();
        //獲取操作方法返回值
        Object result = joinPoint.proceed();
        String returnValue = JSONObject.toJSONString(result);
        operateLog.setReturnValue(returnValue.toString());
        //獲取操作結(jié)束時間
        long end = System.currentTimeMillis();
        //獲取操作耗時
        operateLog.setCostTime((end-begin));
        operateLogMapper.insert(operateLog);
        return  result;

    }
}

管理事務(wù)

1. 添加依賴

在 pom.xml 中添加 MyBatis-Plus 和 AOP 的依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.0</version> <!-- 根據(jù)需要選擇版本 -->
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

2. 配置 MyBatis-Plus

在 application.yml 中配置 MyBatis-Plus 和數(shù)據(jù)源:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/your_database
    username: your_username
    password: your_password
    driver-class-name: com.mysql.cj.jdbc.Driver
  mybatis-plus:
    mapper-locations: classpath*:/mappers/**/*.xml

3. 創(chuàng)建事務(wù)切面

創(chuàng)建一個事務(wù)切面類:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Aspect
@Component
public class TransactionAspect {

    @Transactional
    @Around("execution(* com.yourpackage.service..*(..))") // 指定需要事務(wù)的業(yè)務(wù)邏輯包
    public Object manageTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result;
        try {
            result = joinPoint.proceed(); // 執(zhí)行目標(biāo)方法
            return result;
        } catch (Exception e) {
            throw e; // 拋出異常以觸發(fā)回滾
        }
    }
}

4. 示例業(yè)務(wù)邏輯類

創(chuàng)建一個服務(wù)類,使用 MyBatis-Plus 進(jìn)行數(shù)據(jù)庫操作:

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

@Service
public class UserService extends ServiceImpl<UserMapper, User> {

    public void createUser(User user) {
        this.save(user); // 調(diào)用 MyBatis-Plus 的 save 方法
    }
}

5. 用戶實(shí)體和 Mapper

  • 定義用戶實(shí)體:
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

@TableName("users") // 數(shù)據(jù)庫表名
public class User {
    @TableId
    private Long id;
    private String name;

    // getters and setters
}
  • Mapper 接口:
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface UserMapper extends BaseMapper<User> {
    // 可以自定義額外的方法
}

6. 創(chuàng)建控制器

在控制器中調(diào)用 UserService 的 createUser 方法:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping
    public String createUser(@RequestBody User user) {
        userService.createUser(user); // 調(diào)用 UserService 的 createUser 方法
        return "User created successfully"; // 返回成功消息
    }
}

7. 啟動類

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

心得

  • 通過以上步驟,你可以在 Spring Boot 項(xiàng)目中整合 AOP 和 MyBatis-Plus,實(shí)現(xiàn)簡單而有效的事務(wù)管理。
  • 這樣,無論是在正常情況下提交事務(wù),還是在出現(xiàn)異常時回滾事務(wù),都能得到很好的支持。

為什么做事務(wù),做事務(wù)有啥用

  • 事務(wù)確保一組操作要么全部成功,要么全部失敗,從而保持?jǐn)?shù)據(jù)的一致性和完整性。
  • 它們在處理銀行轉(zhuǎn)賬、訂單處理等場景時尤其重要,可以防止數(shù)據(jù)不一致、部分更新或系統(tǒng)故障導(dǎo)致的數(shù)據(jù)丟失。
  • 通過事務(wù),確保即使在異常情況下,數(shù)據(jù)狀態(tài)依然可靠。

那為什么要結(jié)合aop去做事務(wù)

  • 結(jié)合 AOP(面向切面編程)可以將事務(wù)管理的邏輯與業(yè)務(wù)邏輯分離,提高代碼的可維護(hù)性和可讀性。
  • 通過 AOP,可以在不修改業(yè)務(wù)代碼的情況下,集中管理事務(wù),簡化代碼結(jié)構(gòu),并實(shí)現(xiàn)事務(wù)的自動化管理,減少重復(fù)代碼,提高開發(fā)效率。

權(quán)限控制

1. 添加依賴

在 pom.xml 中添加 AOP 相關(guān)依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2. 創(chuàng)建權(quán)限注解

定義一個自定義注解 @RequiresPermission:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresPermission {
    String value();
}

3. 創(chuàng)建切面類

創(chuàng)建切面類,使用 @Aspect 注解來定義切面,處理權(quán)限控制邏輯:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class PermissionAspect {

    @Autowired
    private UserService userService; // 獲取用戶服務(wù)

    @Around("@annotation(requiresPermission)") // 攔截使用 @RequiresPermission 注解的方法
    public Object checkPermission(ProceedingJoinPoint joinPoint, RequiresPermission requiresPermission) throws Throwable {
        String requiredPermission = requiresPermission.value(); // 獲取所需權(quán)限

        // 權(quán)限檢查邏輯
        if (!hasPermission(requiredPermission)) {
            throw new SecurityException("Permission denied: " + requiredPermission);
        }

        return joinPoint.proceed(); // 執(zhí)行目標(biāo)方法
    }

    private boolean hasPermission(String permission) {
        User currentUser = userService.getCurrentUser(); // 獲取當(dāng)前用戶

        if (currentUser == null) {
            return false; // 用戶未登錄
        }

        return currentUser.getPermissions().contains(permission); // 檢查權(quán)限
    }
}

在使用 AOP 時,@RequiresPermission 注解是一個標(biāo)記,它本身并不直接傳遞參數(shù)。Spring AOP 在攔截帶有該注解的方法時,會自動創(chuàng)建該注解的實(shí)例,并將其作為參數(shù)傳遞給

checkPermission 方法。這是通過 AOP 框架的代理機(jī)制實(shí)現(xiàn)的,而不是通過顯式調(diào)用。具體來說,當(dāng)被注解的方法被調(diào)用時,AOP 會攔截這個調(diào)用并注入相應(yīng)的注解信息。

permission 參數(shù)來源于 @RequiresPermission 注解的 value() 方法。在 checkPermission 方法中,當(dāng)該方法攔截到一個使用 @RequiresPermission 注解的方法時,Spring AOP 會將該注解的實(shí)例作為第二個參數(shù)傳遞給 checkPermission 方法。因此,你可以通過調(diào)用 requiresPermission.value() 來獲取注解中定義的權(quán)限字符串。

4. 使用權(quán)限注解

在需要進(jìn)行權(quán)限控制的方法上使用自定義注解

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @GetMapping("/admin")
    @RequiresPermission("ADMIN_ACCESS")
    public String adminAccess() {
        return "Welcome, admin!";
    }
}

5. 配置 Spring Boot

確保 Spring Boot 應(yīng)用程序能夠掃描到切面和自定義注解。通常情況下,只需在主類中添加 @EnableAspectJAutoProxy 注解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

@EnableAspectJAutoProxy 注解的作用是啟用 Spring 的 AOP(面向切面編程)支持,允許使用 AspectJ 的代理機(jī)制來實(shí)現(xiàn)切面。具體來說,它有以下幾個功能:

1.啟用代理

它告訴 Spring 創(chuàng)建代理對象,這些代理對象可以攔截方法調(diào)用并執(zhí)行切面邏輯。

2.支持注解

當(dāng)你在代碼中使用注解(如 @Around、@Before 等)時,@EnableAspectJAutoProxy 會使這些注解生效,從而實(shí)現(xiàn)方法攔截和切面邏輯的執(zhí)行。

3.簡化配置

通過添加這個注解,開發(fā)者不需要額外的 XML 配置,只需通過注解來定義切面和增強(qiáng),減少了配置的復(fù)雜性。

在主類中添加這個注解后,Spring Boot 應(yīng)用會自動掃描到切面類并將其注冊到應(yīng)用上下文中,從而實(shí)現(xiàn)所需的 AOP 功能。

AOP的五種通知類型包括‌

  • 前置通知(@Before)‌
  • 后置通知(@After)‌
  • 返回通知(@AfterReturning)‌
  • 異常通知(@AfterThrowing)‌
  • 環(huán)繞通知(@Around)‌

每種通知類型都有其特定的用途和場景,可以根據(jù)實(shí)際需求選擇使用。

總結(jié)

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • springboot?+rabbitmq+redis實(shí)現(xiàn)秒殺示例

    springboot?+rabbitmq+redis實(shí)現(xiàn)秒殺示例

    本文主要介紹了springboot?+rabbitmq+redis實(shí)現(xiàn)秒殺示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Java實(shí)現(xiàn)異步延遲隊(duì)列的方法詳解

    Java實(shí)現(xiàn)異步延遲隊(duì)列的方法詳解

    目前系統(tǒng)中有很多需要用到延時處理的功能,本文就為大家介紹了Java實(shí)現(xiàn)異步延遲隊(duì)列的方法,文中的示例代碼講解詳細(xì),需要的可以參考一下
    2023-03-03
  • java中反射和注解的簡單使用方法

    java中反射和注解的簡單使用方法

    相信大家對注解和反射應(yīng)該并不陌生,在現(xiàn)在信息飛速發(fā)展的年代,各種優(yōu)秀的框架或許都離不開注解的使用,這篇文章主要給大家介紹了關(guān)于java中反射和注解的簡單使用方法,需要的朋友可以參考下
    2021-08-08
  • 淺談java監(jiān)聽器的作用

    淺談java監(jiān)聽器的作用

    這篇文章主要介紹了淺談java監(jiān)聽器的作用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • Intellij IDEA 添加jar包的三種方式(小結(jié))

    Intellij IDEA 添加jar包的三種方式(小結(jié))

    這篇文章主要介紹了Intellij IDEA 添加jar包的三種方式(小結(jié)),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • 詳解spring batch的使用和定時器Quart的使用

    詳解spring batch的使用和定時器Quart的使用

    spring Batch是一個基于Spring的企業(yè)級批處理框架,它通過配合定時器Quartz來輕易實(shí)現(xiàn)大批量的數(shù)據(jù)讀取或插入,并且全程自動化,無需人員管理
    2017-08-08
  • java mybatis框架實(shí)現(xiàn)多表關(guān)系查詢功能

    java mybatis框架實(shí)現(xiàn)多表關(guān)系查詢功能

    這篇文章主要介紹了java mybatis框架實(shí)現(xiàn)多表關(guān)系查詢,基于Maven框架的整體設(shè)計(jì) —— 一多一的關(guān)系,文中通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-10-10
  • mybatis-plus查詢源碼詳解

    mybatis-plus查詢源碼詳解

    這篇文章主要介紹了mybatis-plus查詢源碼解讀,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03
  • java 獲取當(dāng)前函數(shù)名的實(shí)現(xiàn)代碼

    java 獲取當(dāng)前函數(shù)名的實(shí)現(xiàn)代碼

    以下是對使用java獲取當(dāng)前函數(shù)名的實(shí)現(xiàn)代碼進(jìn)行了介紹。需要的朋友可以過來參考下
    2013-08-08
  • SpringCloud如何使用Eureka實(shí)現(xiàn)服務(wù)之間的傳遞數(shù)據(jù)

    SpringCloud如何使用Eureka實(shí)現(xiàn)服務(wù)之間的傳遞數(shù)據(jù)

    這篇文章主要介紹了SpringCloud使用Eureka實(shí)現(xiàn)服務(wù)之間的傳遞數(shù)據(jù)操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06

最新評論