【问题标题】:spring-boot-starter-aop around annotated interface's method won't advice my aspectspring-boot-starter-aop 围绕带注释的接口的方法不会建议我的方面
【发布时间】:2017-09-25 16:29:44
【问题描述】:

我有以下实现:

public interface BusinessResource {

    @RequiresAuthorization
    public ResponseEnvelope getResource(ParamObj param);
}

@Component
public class BusinessResourceImpl implements BusinessResource {

    @Autowired
    public Response getResource(ParamObj param) {
        return Response.ok().build();
    }
}

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

@Aspect
@Component
public class AuthorizerAspect {

    protected static final Logger LOGGER =
                      LoggerFactory.getLogger(AuthorizerAspect.class);

    @Autowired
    public AuthorizerAspect() {
        LOGGER.info("Break point works here..." +
        "so spring is creating the aspect as a component...");
    }

    @Around(value="@annotation(annotation)")
    public Object intercept(ProceedingJoinPoint jp,
                            RequiresAuthorization annotation) throws Throwable {
        LOGGER.info("BEGIN");
        jp.proceed();
        LOGGER.info("END");
    }
}

使用 spring-boot-starter-aop 依赖项正确配置了 maven 依赖项。那么如果在 BusinessResource 接口的声明方法上使用了@RequiresAuthorizationAuthorizerAspect 不会拦截 getResource 方法,但是,如果我现在更改实现以在 BusinessResourceImpl 类中注释相同的方法,则会发生方面。

注意:使用接口级别的注解,甚至不会创建代理,而放置在实现级别的注解将为资源创建代理。

问题是:有没有办法建议只在界面上出现注释的对象?

【问题讨论】:

    标签: aop aspectj spring-aop pointcut


    【解决方案1】:

    对于那些像我一样找不到直接方法通过代理对 Spring AOP 的限制进行排序的人来说,这种替代方案是否有用:

    public interface BusinessResource {
    
        @RequiresAuthorization
        public ResponseEnvelope getResource(ParamObj param);
    }
    

    @Component
    public class BusinessResourceImpl implements BusinessResource {
    
        @Autowired
        public Response getResource(ParamObj param) {
            return Response.ok().build();
        }
    }
    

    import import org.aopalliance.intercept.MethodInvocation;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class AuthorizerAspect {
    
        protected static final Logger LOGGER =
                          LoggerFactory.getLogger(AuthorizerAspect.class);
    
        @Autowired
        public AuthorizerAspect() {
            LOGGER.info("Break point works here..." +
            "so spring is creating the aspect as a component...");
        }
    
        public Object invoke(MethodInvocation invocation) throws Throwable {
            LOGGER.info("BEGIN");
            invocation.proceed();
            LOGGER.info("END");
        }
    
        @Bean
        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
            return new DefaultAdvisorAutoProxyCreator();
        }
    
        @Bean("requiresAuthorizationPointcut")
        public AbstractPointcutAdvisor createPointcut() {
            return new AbstractPointcutAdvisor() {
    
                private static final long serialVersionUID = 4733447191475535406L;
    
                @Override
                public Advice getAdvice() {
                    return AuthorizerAspect.this;
                }
    
                @Override
                public Pointcut getPointcut() {
                    return  new StaticMethodMatcherPointcut() {
                        @Override
                        public boolean matches(Method method, Class<?> targetClass) {
                            if (method.isAnnotationPresent(RequiresAuthorization.class)) {
                                return true;
                            }
                            if (method.getDeclaringClass().isInterface()) {
                                String methodName = method.getName();
                                try {
                                    Method targetMethod = targetClass.getMethod(methodName, method.getParameterTypes());
                                    return targetMethod != null && targetMethod.isAnnotationPresent(RequiresAuthorization.class);
                                } catch (NoSuchMethodException |
                                         SecurityException e) {
                                    LOGGER.debug("FAILURE LOG HERE",
                                                 e.getMessage());
                                    return false;
                                }
                            }
                            return method.isAnnotationPresent(RequiresAuthorization.class);
                        }
                    };
                }
            };
        }
    }
    

    如您所见,我们使用方法拦截器对其进行排序。

    【讨论】:

    • 请在提交答案之前确保没有问题。调用方法返回在哪里? Advice 类的包在哪里?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多