🔑 Nepxion Matrix is an AOP framework integrated with Spring AutoProxy, Spring Registrar and Spring Import Selector with high universality, robustness, flexibility and usability 面向注解的业务场景,包括代理、拦截、开关
Nepxion Matrix是一款集成Spring AutoProxy,Spring Registrar和Spring Import Selector三种机制的AOP框架,具有很高的通用性、健壮性、灵活性和易用性
它统一封装接口(Spring)代理和类代理(CGLIB),注解无论在接口和类的头部或者方法上,都可以让业务端执行有效切面,可以轻松快速实现对接口或者类的复杂代理业务。代码参考com.nepxion.matrix.proxy,示例参考matrix-spring-boot-proxy-example
实现接口走Spring代理,类走CGLIB代理
实现通用代理和额外代理两种机制
实现同一进程中,可以接口代理和类代理同存
实现对类或者接口名上注解Annotation,方法上注解Annotation的快速扫描,并开放处理接口供业务端实现
实现“只扫描不代理”,“既扫描又代理”;代理模式ProxyMode,支持“只代理类或者接口名上注解”、“只代理方法上的注解”、“全部代理”三种模式;扫描模式ScanMode,支持“只扫描类或者接口名上注解”、“只扫描方法上的注解”、“全部扫描”三种模式
实现“代理和扫描多个注解“
实现“支持多个切面实现类Interceptor做调用拦截”
实现“自身调用自身的注解方法,达到切面效果”,提供自动装配(Spring 4.3.X以上的版本支持)和AopContext.currentProxy()两种方式
实现“只扫描指定目录”和“扫描全局目录”两种方式
实现根据Java8的特性来获取注解对应方法上的变量名(不是变量类型),支持标准反射和字节码CGLIG(ASM library)来获取,前者适用于接口代理,后者适用于类代理
标准反射的方式,需要在IDE和Maven里设置"-parameters"的Compiler Argument。参考如下:
实现象@FeignClient注解那样,只有接口没有实现类,就能实现注入和动态代理。代码参考com.nepxion.matrix.registrar,示例参考matrix-spring-boot-registrar-example
实现象@EnableCircuitBreaker注解那样,入口加上@EnableMyAnnotation,自动初始化对应的Configuration。代码参考com.nepxion.matrix.selector,示例参考matrix-spring-boot-selector-example
Matrix框架一般可以应用到如下场景中:
参考@FeignClient的用法
参考@EnableCircuitBreaker的用法
最新版本兼容
<dependency>
<groupId>com.nepxion</groupId>
<artifactId>matrix-aop</artifactId>
<version>${matrix.version}</version>
</dependency>
拦截实现类中@Component注解一定要加名称,因为全局拦截机制是根据名称BeanName来的
@Component("myInterceptor1")
public class MyInterceptor1 extends AbstractInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
......
}
}
调用入口1,通过全局拦截器实现对类头部注解的扫描和代理,详细用法可参考示例3
package com.nepxion.matrix.proxy.simple.aop;
/**
* <p>Title: Nepxion Matrix</p>
* <p>Description: Nepxion Matrix AOP</p>
* <p>Copyright: Copyright (c) 2017-2050</p>
* <p>Company: Nepxion</p>
* @author Haojun Ren
* @version 1.0
*/
import java.lang.annotation.Annotation;
import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.stereotype.Component;
import com.nepxion.matrix.proxy.aop.DefaultAutoScanProxy;
import com.nepxion.matrix.proxy.mode.ProxyMode;
import com.nepxion.matrix.proxy.mode.ScanMode;
// 通过全局拦截器实现对类头部注解的扫描和代理
// 该类描述的逻辑是,目标接口或者类头部如果出现了MyAnnotation1注解,那么该接口或者类下面所有的方法都会被执行扫描和代理,代理类为MyInterceptor1
@Component("myAutoScanProxyForClass")
public class MyAutoScanProxyForClass extends DefaultAutoScanProxy {
private static final long serialVersionUID = -5968030133395182024L;
// 多个包路径,用“;”分隔
private static final String SCAN_PACKAGES = "com.nepxion.matrix.proxy.simple";
@SuppressWarnings("rawtypes")
private Class[] commonInterceptorClasses;
@SuppressWarnings("rawtypes")
private Class[] classAnnotations;
public MyAutoScanProxyForClass() {
super(SCAN_PACKAGES, ProxyMode.BY_CLASS_ANNOTATION_ONLY, ScanMode.FOR_CLASS_ANNOTATION_ONLY);
}
@SuppressWarnings("unchecked")
@Override
protected Class<? extends MethodInterceptor>[] getCommonInterceptors() {
if (commonInterceptorClasses == null) {
commonInterceptorClasses = new Class[] { MyInterceptor1.class };
}
return commonInterceptorClasses;
}
@SuppressWarnings("unchecked")
@Override
protected Class<? extends Annotation>[] getClassAnnotations() {
if (classAnnotations == null) {
classAnnotations = new Class[] { MyAnnotation1.class };
}
return classAnnotations;
}
@Override
protected void classAnnotationScanned(Class<?> targetClass, Class<? extends Annotation> classAnnotation) {
System.out.println("Class annotation scanned, targetClass=" + targetClass + ", classAnnotation=" + classAnnotation);
}
}
调用入口2,通过额外拦截器实现对方法头部注解的扫描和代理
package com.nepxion.matrix.proxy.simple.aop;
/**
* <p>Title: Nepxion Matrix</p>
* <p>Description: Nepxion Matrix AOP</p>
* <p>Copyright: Copyright (c) 2017-2050</p>
* <p>Company: Nepxion</p>
* @author Haojun Ren
* @version 1.0
*/
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.nepxion.matrix.proxy.aop.DefaultAutoScanProxy;
import com.nepxion.matrix.proxy.mode.ProxyMode;
import com.nepxion.matrix.proxy.mode.ScanMode;
import com.nepxion.matrix.proxy.simple.service.MyService2Impl;
// 通过额外拦截器实现对方法头部注解的扫描和代理
// 该类描述的逻辑是,目标接口或者类的某个方法上如果出现了MyAnnotation2注解,那么该接口或者类下面所有的方法都会被执行扫描和代理,并为该接口或者类指定一个具体的代理类为MyInterceptor2
@Component("myAutoScanProxyForMethod")
public class MyAutoScanProxyForMethod extends DefaultAutoScanProxy {
private static final long serialVersionUID = -481395242918857264L;
private static final String[] SCAN_PACKAGES = { "com.nepxion.matrix.proxy.simple" };
@SuppressWarnings("rawtypes")
private Class[] methodAnnotations;
@Autowired
private MyInterceptor2 myInterceptor2;
private Object[] myInterceptor2Array;
public MyAutoScanProxyForMethod() {
super(SCAN_PACKAGES, ProxyMode.BY_METHOD_ANNOTATION_ONLY, ScanMode.FOR_METHOD_ANNOTATION_ONLY);
}
@Override
protected Object[] getAdditionalInterceptors(Class<?> targetClass) {
if (targetClass == MyService2Impl.class) {
return getMyInterceptor2Array();
}
return null;
}
private Object[] getMyInterceptor2Array() {
if (myInterceptor2Array == null) {
myInterceptor2Array = new Object[] { myInterceptor2 };
}
return myInterceptor2Array;
}
@SuppressWarnings("unchecked")
@Override
protected Class<? extends Annotation>[] getMethodAnnotations() {
if (methodAnnotations == null) {
methodAnnotations = new Class[] { MyAnnotation2.class };
}
return methodAnnotations;
}
@Override
protected void methodAnnotationScanned(Class<?> targetClass, Method method, Class<? extends Annotation> methodAnnotation) {
System.out.println("Method annotation scanned, targetClass=" + targetClass + ", method=" + method + ", methodAnnotation=" + methodAnnotation);
}
}
更复杂的用法请参考com.nepxion.matrix.proxy.complex目录下的代码
参考matrix-spring-boot-registrar-example
参考matrix-spring-boot-selector-example
微信、钉钉、公众号和文档