在service上通过注解实现对远程应用服务的统一拦截AOP

一、增加注解

增加一个作用于类及方法上的注解,并且参数中可以指明这是对哪个应用的拦截。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ProxyInterceptor {

    /**
     * 第三方应用唯一标识
     */
    AppCode appCode();

二、让拦截器注解在运行时生效,需要增加一个切面

public class ProxyInterceptorAdvisor extends AbstractPointcutAdvisor {

    private static final long serialVersionUID = -3969619570449156144L;

    private Advice advice;
    private Pointcut pointcut;

    public ProxyInterceptorAdvisor(Class<? extends Annotation> annotationType, MethodInterceptor interceptor) {
        this.pointcut = buildPointcut(annotationType);
        this.advice = interceptor;
    }

    @Override
    public Pointcut getPointcut() {
        return this.pointcut;
    }

    @Override
    public Advice getAdvice() {
        return this.advice;
    }

    private Pointcut buildPointcut(Class<? extends Annotation> annotationType) {
        ComposablePointcut result = null;
        // 类级别
        Pointcut cpc = new AnnotationMatchingPointcut(annotationType, true);
        // 方法级别
        Pointcut mpc = AnnotationMatchingPointcut.forMethodAnnotation(annotationType);
        // 对于类和方法上都可以添加注解的情况
        // 类上的注解,最终会将注解绑定到每个方法上
        if (result == null) {
            result = new ComposablePointcut(cpc);
        }
        return result.union(mpc);
    }
}

 

三、拦截器的业务处理

此时只要在业务Service上添加了ProxyInterceptor注解就可以被如下逻辑拦截

Component
@Order(Integer.MIN_VALUE)
public class ProxyInterceptorProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor
    implements InitializingBean, ApplicationContextAware {

    private static final long serialVersionUID = 7370491915785512783L;

    @SuppressWarnings("unused")
    private ApplicationContext applicationContext;

    @Override
    public void afterPropertiesSet() throws Exception {
        this.advisor = new ProxyInterceptorAdvisor(ProxyInterceptor.class, new ProxyMethodInterceptor());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    private class ProxyMethodInterceptor implements MethodInterceptor {

        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            Class<?> proxyClass = invocation.getThis().getClass();
            Method method = invocation.getMethod();
            ProxyInterceptor typeInterceptor = proxyClass.getAnnotation(ProxyInterceptor.class);
            ProxyInterceptor methodInterceptor = method.getAnnotation(ProxyInterceptor.class);
            // 优先以方法上的注解为准
            ProxyInterceptor interceptor = methodInterceptor != null ? methodInterceptor : typeInterceptor;
            AppCode app = interceptor.appCode();
            Object result = null;
            try {
                // 被拦截的是私有方法,则直接执行
                if (!Modifier.isPublic(method.getModifiers())) {
                    return invocation.proceed();
                }
                String className = proxyClass.getSimpleName();
                String methodName = method.getName();
                Object args[] = invocation.getArguments();
                log.info(app + "=request=" + className + "." + methodName + ",args:"
                    + JSON.toJSONString(args));
                result = invocation.proceed();
                log.info(app + "=response=" + className + "." + methodName + ",result:"
                    + JSON.toJSONString(result));
                return result;
            }  catch (ProxyServiceException e) {
                e.setApp(app);
                log.error("ProxyServiceException:" + JSON.toJSONString(result), e);
                throw e;
            } catch (Exception e) {
                log.error("Exception:" + JSON.toJSONString(result), e);
                throw new ProxyServiceException(app, e.getMessage(), e);
            }
        }
    }
}

四、使用拦截器

在类上添加注解,并指明这个类是哪个远程应用提供的服务。

@Service
@ProxyInterceptor(appCode = AppCode.CASE)
public class CaseServiceProxy {
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值