信息发布→ 登录 注册 退出

Spring AOP如何在注解上使用SPEL表达式注入对象

发布时间:2026-01-11

点击量:
目录
  • 在注解上使用SPEL表达式注入对象
    • 场景描述
    • 具体案例
    • 补充
  • Spring属性注入方式之SPEL表达式

    在注解上使用SPEL表达式注入对象

    场景描述

    在平时开发中,我们经常通过定义一些注解,进行轻量级开发。

    今天主要研究的内容是关于如何在注解上通过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<String> allPermissions = Arrays.asList("user:save", "user:delete", "user:edit");
            return allPermissions.contains(permission);
        }     
    }

    定义切面

    • 通过@Before注解定义前置切面
    • 通过注入spelExpressionParser解析器,用于解析spel表达式
    • 实例化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";
        }
    }

    补充

    通配符匹配

    // import org.springframework.util.PatternMatchUtils
    List<String> allPermissions = Arrays.asList("user:save", "user:delete", "user:edit");
    return allPermissions.stream().anyMatch(item -> PatternMatchUtils.simpleMatch(permission, item));

    Spring属性注入方式之SPEL表达式

    <bean id="categroy" class="com.test.inject.Category" p:cateName="服装"></bean>
    <bean id="calculate" class="com.test.inject.PriceCalculate"></bean>
    <bean id="product" class="com.test.inject.Product" p:name="A21的T恤" p:categroy-ref="categroy">
      <property name="price" value="#{calculate.calPrice()}"></property>
    </bean>

    spel表达式的好处就是,我们可以使用定义好的某个类中的方法来产生值,然后注入给所需要的对象使用

    比较适用于比较复杂的bean注入

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

    在线客服
    服务热线

    服务热线

    4008888355

    微信咨询
    二维码
    返回顶部
    ×二维码

    截屏,微信识别二维码

    打开微信

    微信号已复制,请打开微信添加咨询详情!