Spring MethodInterceptor 实现注解+SpEL表达式AOP功能
前言
源码级:实现代码是通过Spring Security 源码仿照的。
网上常见的方式 Spring框架提供的:DefaultPointcutAdvisor + AspectJExpressionPointcut或AnnotationMatchingPointcut
本文采用的是全自定义的方式。
定义注解
常规固定写法
@Target({METHOD, TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface PreAspect {
String value();
}
Pointcut 切入点
常用的切入点:AspectJExpressionPointcut或AnnotationMatchingPointcut
StaticMethodMatcherPointcut
静态方法切入点匹配器
class MethodAspectMetadataSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
/**
* 此方法项目启动的时候遍历项目全部方法,需要拦截的方法返回true。
* attributeSource 自定义功能类:查询方法是否被 @PreAspect 注解修饰
*/
public boolean matches(Method m, Class targetClass) {
Collection<ConfigAttribute> attributes = attributeSource.getAttributes(m, targetClass);
return attributes != null && !attributes.isEmpty();
}
}
Pointcut Advisor
继承AbstractPointcutAdvisor 自定义实现
public class MethodAspectMetadataSourceAdvisor extends AbstractPointcutAdvisor {
private transient MethodAspectMetadataSource attributeSource;
private transient MethodInterceptor interceptor;
private final Pointcut pointcut = new MethodAspectMetadataSourcePointcut();
public MethodAspectMetadataSourceAdvisor(MethodInterceptor interceptor, MethodAspectMetadataSource attributeSource) {
this.interceptor = interceptor;
this.attributeSource = attributeSource;
}
@Override
public Pointcut getPointcut() {
return pointcut;
}
@Override
public Advice getAdvice() {
return interceptor;
}
// ~ 内部类
// =================================================================================================================
class MethodAspectMetadataSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
public boolean matches(Method m, Class targetClass) {
Collection<ConfigAttribute> attributes = attributeSource.getAttributes(m, targetClass);
return attributes != null && !attributes.isEmpty();
}
}
}
扩展
- AspectJExpressionPointcutAdvisor
内部已经 new AspectJExpressionPointcut();
MethodInterceptor
public class MethodAspectInterceptor extends AbstractAspectInterceptor implements
MethodInterceptor {
private MethodAspectMetadataSource aspectMetadataSource;
public void setAspectMetadataSource(MethodAspectMetadataSource newSource) {
this.aspectMetadataSource = newSource;
}
@Override
public Class<?> getSecureObjectClass() {
return MethodInvocation.class;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
InterceptorStatusToken token = super.beforeInvocation(mi);
Object result;
try {
result = mi.proceed();
System.out.println(result);
} finally {
super.finallyInvocation(token);
}
return super.afterInvocation(token, result);
}
@Override
public AspectMetadataSource obtainAspectMetadataSource() {
return this.aspectMetadataSource;
}
}
源码
源码后续放上。。。