preface

In Spring Aop, we can take the arguments to the interception method, and if we can combine them with SPEL expressions, we can achieve much more flexible functionality. A typical implementation has Spring’s cache annotations:

@Cacheable(value = "user", key = "#id", condition = "#id lt 10")
public User conditionFindById(final Long id) {}Copy the code
@Caching(put = {
@CachePut(value = "user", key = "#user.id"),
@CachePut(value = "user", key = "#user.username"),
@CachePut(value = "user", key = "#user.email")})public User save(User user) {
Copy the code

This article describes how to parse SPEL expressions in AOP programming, providing several general methods.

I won’t go over the way Spring implements AOP using custom annotations here, but will focus on parsing SPEL.

To prepare

The implementation is very simple, Spring itself provides a simple API, we just need to get:

  • Methods:Method method
  • Method parameters:Object[] arguments
  • Spel expression:String spel

These can be obtained from the AOP entry method parameter ProceedingJoinPoint.

Spel expressions are obviously obtained from custom annotations, and methods and parameters are obtained as follows:

Obtaining method:

private Method getMethod(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        if (method.getDeclaringClass().isInterface()) {
            try {
                method = joinPoint
                        .getTarget()
                        .getClass()
                        .getDeclaredMethod(joinPoint.getSignature().getName(),
                                method.getParameterTypes());
            } catch (SecurityException | NoSuchMethodException e) {
                throw newRuntimeException(e); }}return method;
    }
Copy the code

Obtain method parameter values:

Object[] arguments = joinPoint.getArgs();
Copy the code

parsing

The next step is to parse the SPEL expression, first defining two properties in the AOP class:

private ExpressionParser parser = new SpelExpressionParser();

private LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
Copy the code

Parsed parameters according to SPEL expression, the results are as follows:

    /** * parses spEL expressions **@param* method method@paramThe arguments parameter *@paramSpel expression *@paramClazz returns the type of result *@paramDefaultResult defaultResult *@returnThe result of executing the SPEL expression */
    private <T> T parseSpel(Method method, Object[] arguments, String spel, Class<T> clazz, T defaultResult) {
        String[] params = discoverer.getParameterNames(method);
        EvaluationContext context = new StandardEvaluationContext();
        for (int len = 0; len < params.length; len++) {
            context.setVariable(params[len], arguments[len]);
        }
        try {
            Expression expression = parser.parseExpression(spel);
            return expression.getValue(context, clazz);
        } catch (Exception e) {
            returndefaultResult; }}Copy the code

conclusion

That’s the key flow for parsing SPEL expressions. In general, the structure of an AOP class looks like this:

@Aspect
public class SpelAspect {

    private ExpressionParser parser = new SpelExpressionParser();
    private LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
    
    @Around(value = @annotation(custom annotation))
    public Object test(ProceedingJoinPoint point) throws Throwable {
        Object obj;
        // Get method parameter values
        Object[] arguments = point.getArgs();
        // Get method
        Method method = getMethod(point);
        // Get the spEL string from the annotation, omit...
        String spel = ...
        // Parse the SPEL expression
        Boolean result = parseSpel(method, arguments, spel, Boolean.class, Boolean.FALSE);
        // Business operation, omit....returnpoint.proceed(); }}Copy the code

This gives you a basic idea and a few general methods (#getMethod, #parseSpel). Now it’s time to use your imagination.

Read the original