Spring AOP如何在注解上使用SPEL表达式注入对象
作者:低脂肪
这篇文章主要介绍了Spring AOP如何在注解上使用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注入
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。