日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Spring AOP 在注解上使用SPEL表達式注入對象

作者:低脂肪 更新時間: 2022-04-22 編程語言

場景描述

在平時開發中,我們經常通過定義一些注解,進行輕量級開發。今天主要研究的內容是關于如何在注解上通過spel表達式注入對象,以此調用注入對象的具體業務處理邏輯,然后在通過對表達式的解析,進而獲取該業務邏輯處理的結果,類似于Spring Security中的@PreAuthorize, @PreAuthorize, @PostAuthorize等注解,本次場景案例以模仿@PreAuthorize注解進行分析。

具體案例

定義@SpelPreAuthorize注解,對標@PreAuthorize

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SpelPreAuthorize {

    String value() default "";
}

定義具體業務邏輯處理類


import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

@Component("ps")
public class PermissionService {
    
    public boolean hasPermission(String permission) {
        List allPermissions = Arrays.asList("user:save", "user:delete", "user:edit");
        return allPermissions.contains(permission);
    } 
    
}

定義切面

  1. 通過@Before注解定義前置切面
  2. 通過注入spelExpressionParser解析器,用于解析spel表達式
  3. 實例化EvaluationContext對象(默認實現tandardEvaluationContext),解析表達式,注入上下文信息,執行具體業務
import com.czf.ebao.data.spel.annoation.SpelPreAuthorize;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class SpelPreAuthorizeAspect {

    /**
     * 注入spring bean 工廠
     */
    @Autowired
    private DefaultListableBeanFactory defaultListableBeanFactory;


    @Before("@annotation(spelPreAuthorize)")
    public void perAuthorize(JoinPoint point, SpelPreAuthorize spelPreAuthorize) {
        String permission = spelPreAuthorize.value();
        // 實例化spel表達式解析器
        SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
        // 解析表達式內容
        Expression expression = spelExpressionParser.parseExpression(permission);
        // 聲明StandardEvaluationContext對象,用于設置上下文對象。
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setBeanResolver(new BeanFactoryResolver(defaultListableBeanFactory));
        Boolean result = expression.getValue(context, Boolean.class);
        if (!result) {
            throw new RuntimeException("該用戶無訪問權限");
        }
    }
}

定義測試類

import com.czf.ebao.data.spel.annoation.SpelPreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/spel")
public class SpelController {
    
    @GetMapping("/hello")
    @SpelPreAuthorize("@pms.hasPermission('user:hello')")
    public String sayHello() {
        return "hello";
    }
}

補充

  1. 通配符匹配
// import org.springframework.util.PatternMatchUtils

List allPermissions = Arrays.asList("user:save", "user:delete", "user:edit");
return allPermissions.stream().anyMatch(item -> PatternMatchUtils.simpleMatch(permission, item));

原文鏈接:https://blog.csdn.net/c17315377559/article/details/121670739

欄目分類
最近更新