Spring AOP核心功能源码分析

这篇“Spring AOP核心功能源码分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Spring AOP核心功能源码分析”文章吧。

    背景

    package com.zxc.boot.proxy;
    public class OrderService {
        public void create() {
            System.out.println("创建订单");
        }
        public void payOrder() {
            System.out.println("支付订单");
        }
    }

    假设你有如上的对象,需要对两个方法前面都插入生成订单号的逻辑,如果是传统的方式就可以直接加入,但是过于麻烦,如果使用spring的话,就可以借助如下的工具类,如

    ProxyFactory

    package com.zxc.boot.proxy;
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.framework.ProxyFactory;
    import java.lang.reflect.Method;
    public class Main {
        public static void main(String[] args) {
            //被代理对象
            OrderService orderService = new OrderService();
            ProxyFactory proxyFactory = new ProxyFactory();
            //设置代理对象
            proxyFactory.setTarget(orderService);
            //添加代理逻辑
            proxyFactory.addAdvice(new MethodBeforeAdvice() {
                @Override
                public void before(Method method, Object[] objects, Object o) throws Throwable {
                    System.out.println("-----生成订单号------");
                }
            });
            //获取代理对象
            OrderService orderServiceProxy = (OrderService) proxyFactory.getProxy();
            orderServiceProxy.create();
            orderServiceProxy.payOrder();
        }
    }

    生成的结果如下(注:这里没有接口,肯定是使用cglib生成的代理对象)

    Spring AOP核心功能源码分析

    是不是很简单呢,底层逻辑都是spring帮我们实现的,而MethodBeforeAdvice就是进行的代理逻辑,它的父接口是

    Advice

    这个简单理解就是对象被代理的逻辑,主要有以下的实现,如

    MethodBeforeAdvice、AfterReturningAdvice、MethodInterceptor等等见名思义

    但是这里有一个问题,我们两个方法都被进行了代理,那么是否有办法实现只代理某个方法,而某些方法不进行代理呢,答案是有的,代码如下

    package com.zxc.boot.proxy;
    import org.aopalliance.aop.Advice;
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.Pointcut;
    import org.springframework.aop.PointcutAdvisor;
    import org.springframework.aop.framework.ProxyFactory;
    import org.springframework.aop.support.StaticMethodMatcherPointcut;
    import java.lang.reflect.Method;
    public class Main2 {
        public static void main(String[] args) {
            //被代理对象
            OrderService orderService = new OrderService();
            ProxyFactory proxyFactory = new ProxyFactory();
            //设置代理对象
            proxyFactory.setTarget(orderService);
            //添加代理逻辑
            proxyFactory.addAdvisor(new PointcutAdvisor() {
                @Override
                public Pointcut getPointcut() {
                    //哪些方法进行代理
                    return new StaticMethodMatcherPointcut() {
                        @Override
                        public boolean matches(Method method, Class<?> aClass) {
                            //方法名为create进行代理
                            return method.getName().equals("create");
                        }
                    };
                }
                //代理逻辑
                @Override
                public Advice getAdvice() {
                    return new MethodBeforeAdvice() {
                        @Override
                        public void before(Method method, Object[] objects, Object o) throws Throwable {
                            System.out.println("-----创建订单-----");
                        }
                    };
                }
                @Override
                public boolean isPerInstance() {
                    return false;
                }
            });
            //获取代理对象
            OrderService orderServiceProxy = (OrderService) proxyFactory.getProxy();
            orderServiceProxy.create();
            orderServiceProxy.payOrder();
        }
    }

    Spring AOP核心功能源码分析

    可以看到,只有创建订单的方法才会添加代理逻辑,而支付订单并不会加入这段逻辑,而核心的功能点就是依赖于Pointcut对象

    Pointcut

    Pointcut简单理解就是切掉,也就是用于判断要在哪些方法或者哪些类注入代理逻辑用的

    Advisor

    而Advisor简单理解就是Advice和Pointcut的组合,spring当中进行代理的逻辑也是用Advisor为维度进行处理的

    以上,就是使用ProxyFactory进行代理逻辑的spring工具类,但是很明显这样使用相对来说还是比较麻烦的,所以spring提供了简易的方式让我们使用这种逻辑,如下

    Spring提供的代理支持

    ProxyFactoryBean

    package com.zxc.boot.proxy;
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.framework.ProxyFactoryBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import java.lang.reflect.Method;
    @Configuration
    @ComponentScan("com.zxc.boot.proxy")
    public class AppConfig {
        @Bean
        public ProxyFactoryBean proxyFactoryBean() {
            ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
            proxyFactoryBean.setTarget(new OrderService());
            proxyFactoryBean.addAdvice(new MethodBeforeAdvice() {
                @Override
                public void before(Method method, Object[] objects, Object o) throws Throwable {
                    System.out.println("-------创建订单-------");
                }
            });
            return proxyFactoryBean;
        }
    }
    package com.zxc.boot.proxy;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    public class SpringApplication {
        public static void main(String[] args) {
            ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
            OrderService orderService = applicationContext.getBean(OrderService.class);
            orderService.create();
            orderService.payOrder();
        }
    }

    Spring AOP核心功能源码分析

    只要进行如上的配置,就可以识别到了,这种方式其实跟原有的差不多,只不过spring帮我们处理了最终会返回对应的代理bean回去,但是还有更简单的方式,如下

    DefaultPointcutAdvisor

    package com.zxc.boot.proxy;
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.aop.support.DefaultPointcutAdvisor;
    import org.springframework.aop.support.NameMatchMethodPointcut;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import java.lang.reflect.Method;
    @Configuration
    @ComponentScan("com.zxc.boot.proxy")
    public class AppConfig2 {
        @Bean
        public OrderService orderService() {
            return new OrderService();
        }
        @Bean
        public DefaultPointcutAdvisor defaultPointcutAdvisor() {
            //方法名称蓝机器
            NameMatchMethodPointcut nameMatchMethodPointcut = new NameMatchMethodPointcut();
            nameMatchMethodPointcut.addMethodName("create");
            //设置拦截和代理逻辑
            DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
            defaultPointcutAdvisor.setPointcut(nameMatchMethodPointcut);
            defaultPointcutAdvisor.setAdvice(new MethodBeforeAdvice() {
                @Override
                public void before(Method method, Object[] args, Object target) throws Throwable {
                    System.out.println("-------创建订单------");
                }
            });
            return defaultPointcutAdvisor;
        }
        //核心类,一个BeanPostProccess后置处理器,用于把扫描到的Advisor进行代理
        @Bean
        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
            return new DefaultAdvisorAutoProxyCreator();
        }
    }
    package com.zxc.boot.proxy;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    public class SpringApplication {
        public static void main(String[] args) {
            ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig2.class);
            OrderService orderService = applicationContext.getBean(OrderService.class);
            orderService.create();
            orderService.payOrder();
        }
    }

    Spring AOP核心功能源码分析

    不用我们多做其他处理,就可以对ioc容器中方法有create的类进行代理,你可以再添加一个类,如下

    package com.zxc.boot.proxy;
    public class UserService {
        public void create() {
            System.out.println("用户service哦哦哦");
        }
    }
    package com.zxc.boot.proxy;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    public class SpringApplication {
        public static void main(String[] args) {
            ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig2.class);
            OrderService orderService = applicationContext.getBean(OrderService.class);
            orderService.create();
            orderService.payOrder();
            UserService userService = applicationContext.getBean(UserService.class);
            userService.create();
        }
    }

    Spring AOP核心功能源码分析

    这样的方式就方便多了

    优化处理

    其实DefaultAdvisorAutoProxyCreator只是需要导入到ioc容器中,所以配置类可以使用import进行处理,效果是一样的,如下

    package com.zxc.boot.proxy;
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.aop.support.DefaultPointcutAdvisor;
    import org.springframework.aop.support.NameMatchMethodPointcut;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    import java.lang.reflect.Method;
    @Configuration
    @ComponentScan("com.zxc.boot.proxy")
    @Import(DefaultAdvisorAutoProxyCreator.class)
    public class AppConfig2 {
        @Bean
        public UserService userService() {
            return new UserService();
        }
        @Bean
        public OrderService orderService() {
            return new OrderSepackage com.zxc.boot.proxy;
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.aop.support.DefaultPointcutAdvisor;
    import org.springframework.aop.support.NameMatchMethodPointcut;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Import;
    import java.lang.reflect.Method;
    @Configuration
    @ComponentScan("com.zxc.boot.proxy")
    @Import(DefaultAdvisorAutoProxyCreator.class)
    public class AppConfig2 {
        @Bean
        public UserService userService() {
            return new UserService();
        }
        @Bean
        public OrderService orderService() {
            return new OrderService();
        }
        @Bean
        public DefaultPointcutAdvisor defaultPointcutAdvisor() {
            //方法名称蓝机器
            NameMatchMethodPointcut nameMatchMethodPointcut = new NameMatchMethodPointcut();
            nameMatchMethodPointcut.addMethodName("create");
            //设置拦截和代理逻辑
            DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
            defaultPointcutAdvisor.setPointcut(nameMatchMethodPointcut);
            defaultPointcutAdvisor.setAdvice(new MethodBeforeAdvice() {
                @Override
                public void before(Method method, Object[] args, Object target) throws Throwable {
                    System.out.println("-------创建订单------");
                }
            });
            return defaultPointcutAdvisor;
        }
    //    //核心类,一个BeanPostProccess后置处理器,用于把扫描到的Advisor进行代理
    //    @Bean
    //    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    //        return new DefaultAdvisorAutoProxyCreator();
    //    }
    }rvice();
        }
        @Bean
        public DefaultPointcutAdvisor defaultPointcutAdvisor() {
            //方法名称蓝机器
            NameMatchMethodPointcut nameMatchMethodPointcut = new NameMatchMethodPointcut();
            nameMatchMethodPointcut.addMethodName("create");
            //设置拦截和代理逻辑
            DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
            defaultPointcutAdvisor.setPointcut(nameMatchMethodPointcut);
            defaultPointcutAdvisor.setAdvice(new MethodBeforeAdvice() {
                @Override
                public void before(Method method, Object[] args, Object target) throws Throwable {
                    System.out.println("-------创建订单------");
                }
            });
            return defaultPointcutAdvisor;
        }
    //    //核心类,一个BeanPostProccess后置处理器,用于把扫描到的Advisor进行代理
    //    @Bean
    //    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    //        return new DefaultAdvisorAutoProxyCreator();
    //    }
    }

    如果你不导入DefaultAdvisorAutoProxyCreator对象,那么代理逻辑就不会生效,本质就是DefaultAdvisorAutoProxyCreator类就是一个BeanPostProcessor处理器,它会针对所有类进行判断然后处理。

    以上就是关于“Spring AOP核心功能源码分析”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程之家行业资讯频道。

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

    相关推荐


    这篇文章主要介绍了spring的事务传播属性REQUIRED_NESTED的原理介绍,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。传统事务中回滚点的使...
    今天小编给大家分享的是一文解析spring中事务的传播机制,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会有所收获...
    这篇文章主要介绍了SpringCloudAlibaba和SpringCloud有什么区别,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。Spring Cloud Netfli...
    本篇文章和大家了解一下SpringCloud整合XXL-Job的几个步骤。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。第一步:整合pom文件,在S...
    本篇文章和大家了解一下Spring延迟初始化会遇到什么问题。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。List 坑列表 = new ArrayList(2);...
    这篇文章主要介绍了怎么使用Spring提供的不同缓存注解实现缓存的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇...
    本篇内容主要讲解“Spring中的@Autowired和@Resource注解怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学...
    今天小编给大家分享一下SpringSecurity怎么定义多个过滤器链的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家
    这篇文章主要介绍“Spring的@Conditional注解怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring的@Con...
    这篇文章主要介绍了SpringCloudGateway的熔断限流怎么配置的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇SpringCloud&nb...
    今天小编给大家分享一下怎么使用Spring解决循环依赖问题的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考
    这篇文章主要介绍“Spring事务及传播机制的原理及应用方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Sp...
    这篇“SpringCloudAlibaba框架实例应用分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价
    本篇内容主要讲解“SpringBoot中怎么使用SpringMVC”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习...
    这篇文章主要介绍“SpringMVC适配器模式作用范围是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringMVC
    这篇“导入SpringCloud依赖失败如何解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家...
    这篇文章主要讲解了“SpringMVC核心DispatcherServlet处理流程是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来
    今天小编给大家分享一下SpringMVCHttpMessageConverter消息转换器怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以...
    这篇文章主要介绍“Spring框架实现依赖注入的原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring框架...
    本篇内容介绍了“Spring单元测试控制Bean注入的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下