spring-boot-starter-aop on annotated interface的方法不会提示我的方面

时间:2017-09-25 16:29:44

标签: aop aspectj spring-aop pointcut

我有以下实现:

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");
    }
}

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

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

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

1 个答案:

答案 0 :(得分:0)

对于那些喜欢我的人来说,这个替代方案对于通过代理找不到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);
                    }
                };
            }
        };
    }
}

因此,您会注意到,我们会使用方法拦截器对其进行排序。