详解原生Spring框架下的类切入点表达式与切入点函数

2023-12-02 19:45

本文主要是介绍详解原生Spring框架下的类切入点表达式与切入点函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

 😉😉 学习交流群:

✅✅1:这是孙哥suns给大家的福利!

✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料

🥭🥭3:QQ群:583783824   📚📚  工作微信:BigTreeJava 拉你进微信群,免费领取!

🍎🍎4:本文章内容出自上述:Spring应用课程!💞💞

💞💞5:以上内容,进群免费领取呦~ 💞💞💞💞

一:类切入点表达式概念

        假设我需要把一个类当中的所有的方法定义为切入点,这样我们可以使用这个类切入点,类切入点指定类为切入点,只不过是这样的一个称呼。
        所有的额外功能还是加在了这个类的全部的方法上,这样的形式是包+类:
        详细的切入点配置如下,测试结果不贴出来了,和其他的一样没啥区别。

1:某一个确定类加入额外功能

        * com.aaa.bbb.impl.*(..)  :类中的所有方法都加入了额外功能,这是第一种语法形式。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="userService" class = "com.pactera.spring.proxy.UserServiceImpl"/><bean id="orderService" class = "com.pactera.spring.proxy.OrderServiceImpl"/>
<!--    <bean id="before" class="com.pactera.spring.dynamic.Before"/>--><bean id = "around" class = "com.pactera.spring.dynamic.Around"/><aop:config><!--这个标签就是用来定义切入点的,expression这个是切入点表达式,代表所有的方法都要加上这个额外功能--><!--所有的方法,都作为切入点作为额外功能。--><aop:pointcut id="pc" expression="execution(* com.pactera.spring.proxy.UserServiceImpl.*(String,..))"/><!--组装,组长的目的就是为了把切入点与额外的功能进行整合--><aop:advisor advice-ref="around" pointcut-ref="pc"/></aop:config>
</beans>

        指定特定类作为切入点,额外功能加入的自然这个类当中的所有的方法都会加上对应的额外功能的。

2:不同包下的同名的类作为类切入点

* *.UserServiceImpl.*(..) -->这样写是不可以的,一个*只能匹配一级包,一般我们的类不会写在com包下的,这样写是有问题的。

如果是多级包应该是这样写:*..表达的就是一级包乃至多级包。* *..UserServiceImpl.*(..):这样写就能匹配多级目录下的这个类了。任何包下的这个类都作为切入点。

3:某个包下的所有的方法作为切入点

我想为所有的某个包下的所有的方法添加切入点:

* com.alibaba.a.*.*(..) -->匹配这个包下的所有类的所有的方法。
注意上边这样写只能在a的包下,不能在a的子包下,子包下是不能被匹配到的。
* com.alibaba..a.*.*(..) -->匹配a包,包括a子包下的所有的类。

将来我们的使用切入点的时候,包的切入点的使用价值更高。使用更加频繁

二:切入点函数

        切入点函数的作用就是用执行切入点表达式的函数        
        excution:最为重要的一个切入点函数,也是功能最全的。执行方法切入点表达式,也可以执行类切入点表达式,也可以执行包切入点表达式
        弊端:excution执行切入点表达式的时候,书写麻烦,比如:execution(* com.alibaba.proxy..*.*(..);这样写起来很麻烦,spring为我们提供了其他的切入点函数,其他的切入点函数只是起到了简化execution切入点函数的作用,功能还是一样的的,本质上是没有任何区别的,简化的事execution书写的复杂度,但是功能上是完全一致的。

1:args函数

        作用:主要用于函数(方法的)参数的匹配,我们研究下这个意思。

        需求1:方法的切入点其他我不关系,参数必须是两个String的方法作为切入点

        execution(* *(String,String)) -->使用excution这样写
        args(String,String) -->使用args这样写。
        代码和测试结果如下:

    <aop:config><!--这个标签就是用来定义切入点的,expression这个是切入点表达式,代表所有的方法都要加上这个额外功能--><!--所有的方法,都作为切入点作为额外功能。-->
<!--        <aop:pointcut id="pc" expression="execution(* com.pactera.spring.proxy.UserServiceImpl.*(String,..))"/>    --><aop:pointcut id="pc" expression="args(String,String))"/><!--组装,组长的目的就是为了把切入点与额外的功能进行整合--><aop:advisor advice-ref="around" pointcut-ref="pc"/></aop:config>

        测试执行结果: 

    /** @Target: 用于测试* login(String,String)这个切入点表达式_测试多个切入点表达形式* @Author: DaShu* @Date: 2021/6/21 20:53* @Result: 这个切入点定义到了login方法,并且具有两个参数,并且两个参数都是String类型;*/@Testpublic void test6(){ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext3.xml");UserService userService = (UserService)ctx.getBean("userService");userService.login("zhangjie","zhangjie");//...........................这里是额外功能...............................//UserServiceImpl.login//-------------------------------这里还是额外功能----------------------------------------}

2:whthin这个函数

        作用:主要用于类、包切入点的表达式的匹配。

        需求:切入点想选择UserServiceImpl这一个类,不关心包
        execution(* *..UserService.*(..)) -->使用execution方式这样写。
        within(*..UserServiceImpl) -->这个不关系包只关心类的书写方法。
        execution(* com.baizhiedu.proxy..*.*(..)) --使用execution这样写。
        within(com.baizhiedu.proxy..*)
        其实这种简化的写法就是在execution函数选择了一些东西,省略了一些东西。

3:@Annotation

        作用:为具有特定注解的方法加入额外功能,这个是最核心的功能

    <aop:config><!--这个标签就是用来定义切入点的,expression这个是切入点表达式,代表所有的方法都要加上这个额外功能--><!--所有的方法,都作为切入点作为额外功能。-->
<!--        <aop:pointcut id="pc" expression="execution(* com.pactera.spring.proxy.UserServiceImpl.*(String,..))"/>    --><aop:pointcut id="pc" expression="@annotation(com.pactera.spring.annotation.Log)"/><!--组装,组长的目的就是为了把切入点与额外的功能进行整合--><aop:advisor advice-ref="around" pointcut-ref="pc"/></aop:config>
/*** @Auther: DaShu* @Date: 2021/6/15 18:58* @Description:*/
public class UserServiceImpl implements UserService{@Override@Logpublic void register(User user) {//这代表的事业务运算+dao的调用,额外功能不写在这里边。System.out.println("UserServiceImpl.register");}@Overridepublic boolean login(String name,String password) {System.out.println("UserServiceImpl.login");return true;}
}

三:切入点函数的逻辑运算

        切入点函数的逻辑运算值得是整合多个切入点函数一起配合工作,进而完成更为复杂的需求
逻辑运算指的就是整合多个切入点函数的,让他们一起起作用,进而满足可能会遇到的更为复杂的需求,基本操作

1:and  与操作

        案例1:方法得叫login,方法参数参数是两个String类型即可。
        execution(* login(String,String))  -->使用原生execution的书写方式
        execution(* login(..))  and  args(String,String)  --使用切入点函数的逻辑运算。
        两个表达式必须同时满足,两者取的是交集

        注意:与操作不能用于同种类型的切入点函数!

2:or  或操作

        两个切入点满足之一即可进行。

3:!非操作

    <aop:config>
<!--        <aop:pointcut id="pc" expression="@annotation(com.spring.annotation.Log) "/>--><aop:pointcut id="pc" expression="@annotation(com.spring.annotation.Log) and !execution(* com.spring.proxy.UserServiceImpl.re*(..))"/><aop:pointcut id="pc01" expression="@annotation(com.spring.annotation.Log) and !execution(* com.spring.proxy.UserServiceImpl.register(..))"/><aop:advisor advice-ref="around" pointcut-ref="pc"/></aop:config>
    @Testpublic void test1() {ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");UserService userService = (UserService) ctx.getBean("userService");userService.register(new User());userService.register01(new User());//UserServiceImpl.register//UserServiceImpl.register01}@Testpublic void test2() {ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");UserService userService = (UserService) ctx.getBean("userService");userService.login("sun", "123456");//...........................这里是额外功能1...............................//UserServiceImpl.login//-------------------------------这里还是外功能2----------------------------------------}

这个非操作使用的是!这个符号。

四:Spring动态代理开发总结

        为什么使用Spring动态代理开发?

        动态代理开发就是代理开发,作用就是通过代理类对目标类或者叫做原始类增加额外的功能,好处就利于原始类的维护,这里代理类的好处,具体到Spring的动态代理的来讲呢,一共是四步,Spring创建目标对象,Spring创建额外功能对象,定义切入点,整合切入点和额外功能。

这篇关于详解原生Spring框架下的类切入点表达式与切入点函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/446572

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Debezium 与 Apache Kafka 的集成方式步骤详解

《Debezium与ApacheKafka的集成方式步骤详解》本文详细介绍了如何将Debezium与ApacheKafka集成,包括集成概述、步骤、注意事项等,通过KafkaConnect,D... 目录一、集成概述二、集成步骤1. 准备 Kafka 环境2. 配置 Kafka Connect3. 安装 D

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.