自定义AOP,学习spring的事务拓展

95 阅读1分钟

刚刚看完spring事务的源码,对它的AOP注入方式很感兴趣,为了更加熟悉,自己写了一个demo,以作后期回忆和使用

咱们就直接上代码了,废话不多说

MyAdvisorConfiguration

@Configuration
public class MyAdvisorConfiguration {

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public MyPointCutAdivser myPointCutAdivser(MyInterceptor myInterceptor){
        MyPointCutAdivser myPointCutAdivser = new MyPointCutAdivser();
        myPointCutAdivser.setAdvice(myInterceptor);
        return myPointCutAdivser;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public MyInterceptor myInterceptor(){
        return new MyInterceptor();
    }
}

这就是个配置类,将MyPointCutAdivser和myInterceptor注入到spring的容器中,@Role(BeanDefinition.ROLE_INFRASTRUCTURE)一定要标注,不然pointcut不生效。

MyPointCutAdivser

public class MyPointCutAdivser extends AbstractBeanFactoryPointcutAdvisor {
    @Override
    public Pointcut getPointcut() {
        MyPoinCut myPoinCut = new MyPoinCut();
        return myPoinCut;
    }
}

这个类主要继承了 AbstractBeanFactoryPointcutAdvisor的抽象类,这个抽象类的结构如下:

image.png

其中有抽象方法getPointcut,主要是提供我们自定义的pointcut,我这里是MyPoinCut,切入点的方式有六种,我这里用的是StaticMethodMatcherPointcut

image.png

MyPoinCut

public class MyPoinCut extends StaticMethodMatcherPointcut {
    @Override
    public boolean matches(Method method, Class<?> targetClass) {
        MyAnno annotation = AnnotationUtils.findAnnotation(method, MyAnno.class);
        if(annotation != null){
            return true;
        }
        return false;
    }
}

意思就是只要有MyAnno的注解的方法,都会走我们自定义的MethodInterceptor

MyInterceptor

public class MyInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("start times: " + System.currentTimeMillis());
        Object proceed = invocation.proceed();
        System.out.println("end times: " + System.currentTimeMillis());
        return proceed;
    }
}

这是自定义的methodinterceptor,我们做了很简单的操作,就是在执行方法的前后打印出时间戳。

为了简单测试,我们就用controller了:

@RestController
@RequestMapping("/test")
public class TestController {

    @GetMapping("/aa")
    @MyAnno
    public Object aa(){
        return "aaaa";
    }
}

看一下执行效果

image.png