文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring AOP核心功能源码分析

2023-07-05 07:16

关注

这篇“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核心功能源码分析”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯