微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

spring 18 动态通知调用

带参数绑定的通知方法调用

点击查看代码
 @Aspect
    static class MyAspect {
        @Before("execution(* foo(..))") // 静态通知调用,不带参数绑定,执行时不需要切点
        public void before1() {
            System.out.println("before1");
        }

        @Before("execution(* foo(..)) && args(x)") // 动态通知调用,需要参数绑定,执行时还需要切点对象
        public void before2(int x) {
            System.out.printf("before2(%d)%n", x);
        }
    }

    static class Target {
        public void foo(int x) {
            System.out.printf("target foo(%d)%n", x);
        }
    }

    @Configuration
    static class MyConfig {
        @Bean
        AnnotationAwareAspectJAutoproxyCreator proxyCreator() {
            return new AnnotationAwareAspectJAutoproxyCreator();
        }

        @Bean
        public MyAspect myAspect() {
            return new MyAspect();
        }
    }

    public static void main(String[] args) throws Throwable {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean(ConfigurationClasspostProcessor.class);
        context.registerBean(MyConfig.class);
        context.refresh();

        AnnotationAwareAspectJAutoproxyCreator creator = context.getBean(AnnotationAwareAspectJAutoproxyCreator.class);
        List<Advisor> list = creator.findEligibleAdvisors(Target.class, "target");

        Target target = new Target();
        ProxyFactory factory = new ProxyFactory();
        factory.setTarget(target);
        factory.addAdvisors(list);
        Object proxy = factory.getProxy(); // 获取代理

        List<Object> interceptorList =
                factory.getInterceptorsAndDynamicInterceptionAdvice(Target.class.getmethod(
                        "foo", int.class), Target.class);
        for (Object o : interceptorList) {
            showDetail(o);
        }

        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>");
        ReflectiveMethodInvocation invocation = new ReflectiveMethodInvocation(
                proxy, target, Target.class.getmethod("foo", int.class),
                new Object[]{100}, Target.class, interceptorList
        ) {}; // spring 内部可以创建匿名子类来创建构造器 protected 的对象

        invocation.proceed();

        /*
            学到了什么
                a. 有参数绑定的通知调用时还需要切点,对参数进行匹配及绑定
                b. 复杂程度高, 性能比无参数绑定的通知调用低
         */
    }

    public static void showDetail(Object o) {
        try {
            Class<?> clazz = Class.forName("org.springframework.aop.framework.InterceptorAndDynamicmethodMatcher");
            if (clazz.isinstance(o)) {
                Field methodMatcher = clazz.getDeclaredField("methodMatcher");
                methodMatcher.setAccessible(true);
                Field methodInterceptor = clazz.getDeclaredField("interceptor");
                methodInterceptor.setAccessible(true);
                System.out.println("环绕通知和切点:" + o);
                System.out.println("\t切点为:" + methodMatcher.get(o));
                System.out.println("\t通知为:" + methodInterceptor.get(o));
            } else {
                System.out.println("普通环绕通知:" + o);
            }
        } catch (Exception e) {
            e.printstacktrace();
        }
    }

  1. 通过 proxyFactory 的 getInterceptorsAndDynamicInterceptionAdvice() 将其他通知统一转换为 MethodInterceptor 环绕通知
  2. 所谓动态通知,体现在上面方法的 DynamicInterceptionAdvice 部分,这些通知调用时因为要为通知方法绑定参数,还需再次利用切点表达式
  3. 动态通知调用复杂程度高,性能较低

”匿名子类写法“:

可参考:https://blog.csdn.net/weixin_39570751/article/details/121253167

点击查看代码
class S18Bean1 {
    public S18Bean1() {

    }

    public void add() {
    }
}
public class S18Bean2 {
    public static void main(String[] args) {
        S18Bean1 s18Bean3 = new S18Bean1() {

        };
        S18Bean1 s18Bean2 = new S18Bean1() {

        };
        System.out.println(s18Bean3.getClass().getName());
        System.out.println(s18Bean2.getClass().getName());
    }
}

在哪个类创建的就以哪个类开头加$数字再加一个空字符命名, Class类的 getSimpleName() 为空,所以真正的名字是空,是匿名的。
点击查看代码

一个包下的字包不属于当前包,当前包中的 protect 成员不能被子包访问。
如果里面有个类有个 protect 修饰的构造器 在子包中访问不了,spring 内部就是通过这个办法创建它的子类调用

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐