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

mac2025-08-30  11

一、增加注解

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

@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)