Spring-13 AOP 动态通知 & 静态通知

50 阅读1分钟

spring-logo-0.jpg

Spring-13 AOP 动态通知 & 静态通知

Spring 源码系列文章会遵循由浅入深,由易到难,由宏观到微观的原则,目标是尽量降低学习难度,而不是一上来就迷失在源码当中. 文章会从一个场景作为出发点,针对性的目的性极强的针对该场景对 Spring 的实现原理,源码进行探究学习。该系列文章会让你收获什么? 从对 Spring 的使用者成为 Spring 专家。该文章会同步在微信公众号 【DevXJava】, 方便在微信客户端阅读。

本章会介绍 AOP 静态通知动态通知, 静态通知很简单是指固定的表达式在编译器就已经确定了,动态通知 的表达式是在每次调用时动态的最终确定的。

image.png

场景
public class AopTest {

    @Aspect
    static class MyAspect {

        // 静态通知
        @Before("execution(* foo(..))")
        public void before1() {
            System.out.println("@Aspect @Before1 ------------------------------");
        }

        // 动态通知
        @Before("execution(* foo(..)) && args(x)")
        public void before2(int x) {
            System.out.println("@Aspect @Before2 ------------------------------ x = " + x);
        }

    }

    static class Target {
        public void foo(int x) {
            System.out.println("Target foo x = " + x);
        }
    }

    public static void main(String[] args) throws Throwable {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        Logger logger = loggerContext.getLogger(AnnotationAwareAspectJAutoProxyCreator.class);
        logger.setLevel(Level.TRACE);

        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

        AnnotationAwareAspectJAutoProxyCreator proxyCreator = new AnnotationAwareAspectJAutoProxyCreator();
        proxyCreator.setBeanFactory(factory);
        factory.addBeanPostProcessor(proxyCreator);

        factory.registerBeanDefinition("myAspect" , BeanDefinitionBuilder
                .genericBeanDefinition(MyAspect.class)
                .getBeanDefinition());

        // findEligibleAdvisors
        Method findEligibleAdvisors = AbstractAdvisorAutoProxyCreator.class.getDeclaredMethod("findEligibleAdvisors", Class.class, String.class);
        findEligibleAdvisors.setAccessible(true);
        List<Advisor> advisors = (List<Advisor>) findEligibleAdvisors.invoke(proxyCreator, Target.class, "target");
        for (Advisor advisor : advisors) {
            System.out.println("advisor => " + advisor);
        }



        Target target = new Target();
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetClass(Target.class);
        proxyFactory.setTargetSource(new SingletonTargetSource(target));

        Object proxy = proxyFactory.getProxy();

        List<Object> chain = proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(Target.class.getDeclaredMethod("foo" , int.class), Target.class);
        for (Object c : chain) {
            System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>> " + c);
        }

        Constructor<ReflectiveMethodInvocation> constructor = ReflectiveMethodInvocation.class.getDeclaredConstructor(Object.class, Object.class, Method.class, Object[].class, Class.class, List.class);
        constructor.setAccessible(true);
        ReflectiveMethodInvocation invocation = constructor.newInstance(proxy , target ,
                Target.class.getDeclaredMethod("foo" , int.class) , new Object[]{666} , Target.class , chain);
        invocation.proceed();
    }

}

动态通知 InterceptorAndDynamicMethodMatcher

image.png

确定动态通知

DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice 方法内会根据 MethodMatcher 判断切面是否为动态通知。

image.png

ReflectiveMethodInvocation#proceed

image.png


DevX 会持续分享 Java 技术干货,如果你觉得本文对你有帮助希望你可以分享给更多的朋友看到。该文章会同步在微信公众号 【DevXJava】, 方便在微信客户端阅读。

DevX 不止于技术