说明
说到对类方法增强,第一时间想到自定义注解,通过aop切面进行实现。这是一种常用做法,但是在某些场景下,如开发公共组件,定义aop切面可能不是最优方案。以后通过原生aop方式,自定义注解,对类方法进行增强。
实现
自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CustomStat {
}
自定义切点
/**
* 切点(Pointcut),按照规则匹配需要代理的方法
*/
@Slf4j
public class CustomPointcut extends StaticMethodMatcherPointcut implements ClassFilter {
@Override
public boolean matches(Class<?> clazz) {
boolean contains = clazz.getName().contains("com.spring.demo.service");
if (contains) {
log.info("CustomPointcut:{}",clazz.getName());
}
return contains;
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
boolean contains = targetClass.getName().contains("com.spring.demo.service");
if (contains) {
log.info("CustomPointcut:{}",targetClass.getName());
}
return contains;
}
}
自定义增强器
public class CustomAnnotationAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware, Ordered {
private Advice advice;
private Pointcut pointcut;
private MethodInterceptor methodInterceptor;
public CustomAnnotationAdvisor(MethodInterceptor methodInterceptor) {
this.methodInterceptor = methodInterceptor;
this.advice = buildAdvice();
this.pointcut = buildPointcut();
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
@Override
public Advice getAdvice() {
return this.advice;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (this.advice instanceof BeanFactoryAware) {
((BeanFactoryAware) this.advice).setBeanFactory(beanFactory);
}
}
protected Advice buildAdvice() {
return methodInterceptor;
}
protected Pointcut buildPointcut() {
//构建切点
Pointcut cpc = new AnnotationMatchingPointcut(CustomStat.class, true);
Pointcut mpc = AnnotationMatchingPointcut.forMethodAnnotation(CustomStat.class);
return new ComposablePointcut(cpc).union(mpc);
}
@Override
public int getOrder() {
return Integer.MAX_VALUE;
}
}
其中构造参数中的MethodInterceptor
为最终代理拦截器
自定义拦截器
@Slf4j
@Component
public class CustomAnnotationInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
//调用的方法和参数
//Method method = invocation.getMethod();
// Object[] arguments = invocation.getArguments();
log.info("start-注解aop拦截器");
Object proceed = invocation.proceed();
log.info("end-注解aop拦截器");
return proceed;
}
}
注册增强器
@Component
public class CustomAnnotationBeanPostProcessor extends AbstractAdvisingBeanPostProcessor implements BeanFactoryAware {
@Resource
private CustomAnnotationInterceptor customAnnotationInterceptor;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
setBeforeExistingAdvisors(true);
CustomAnnotationAdvisor advisor = new CustomAnnotationAdvisor(customAnnotationInterceptor);
advisor.setBeanFactory(beanFactory);
this.advisor = advisor;
}
}
测试
@Override
@CustomStat
public void printWork() {
System.out.println("WorkServiceImpl1");
}
结果
2024-05-21 08:55:26.486 INFO 41351 --- [nio-8081-exec-5] c.s.d.a.CustomAnnotationInterceptor : start-注解aop拦截器
WorkServiceImpl1
2024-05-21 08:55:26.486 INFO 41351 --- [nio-8081-exec-5] c.s.d.a.CustomAnnotationInterceptor : end-注解aop拦截器