Java进阶知识22 Spring execution 切入点表达式
1、概述
切入点(execution ):可以对指定的方法进行拦截,从而给指定的类生成代理对象。(拦截谁,就是在谁那里切入指定的程序/方法)
格式:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
参数解析:
modifiers-pattern?:指定方法的修饰符,支持通配符,该部分可以省略。(public/private/protected)
ret-type-pattern:指定方法的返回值类型,支持通配符,可以使用 * 来匹配所有的返回值类型。
declaring-type-pattern?:指定方法所属的类,支持通配符,该部分可以省略。(要切入的类:class)
name-pattern:指定要匹配的方法名,支持通配符,可以使用"*"通配符来匹配所有方法。(要切入的方法)
param-pattern:指定方法声明中的形参列表,支持两个通配符,即"*"和"..",其中“*”代表一个任意类型的参数,而“..”代表零个或多个任意类型的参数。例如,() 匹配一个不接受任何参数的方法,而(..) 匹配一个接受任意数量参数的方法,(*)匹配了一个接受一个任何类型的参数的方法,(*,String)匹配了一个接受两个参数的方法,其中第一个参数是任意类型,第二个参数必须是String类型。(要切入的方法的参数列表)
throws-pattern:指定方法声明抛出的异常,支持通配符,该部分可以省略。
切入点语法常用的几种:
<!-- 切入点表达式语法: -->
<!-- 【1、拦截所有public方法】 -->
<aop:pointcut expression="execution(public * *(..))" id="pt"/>
4
<!-- 【2、拦截所有save开头的方法】 -->
<aop:pointcut expression="execution(* save*(..))" id="pt"/>
7
<!-- 【3、拦截指定类的指定方法, 拦截时候一定要定位到方法】 -->
<aop:pointcut expression="execution(* com.shore.dao.impl.UserDao.save(..))" id="pt"/> <!-- 【4、拦截指定类的所有方法】 -->
<aop:pointcut expression="execution(* com.shore.dao.impl.UserDao.*(..))" id="pt"/>
<!-- 【5、拦截指定包,以及其自包下所有类的所有方法】 -->
<aop:pointcut expression="execution(* com..*.*(..))" id="pt"/>
<!-- 【6、多条件】 -->
<!-- 或:|| or -->
<aop:pointcut expression="execution(* com.shore.dao.impl.UserDao.save(..)) || execution(* com.shore.dao.impl.MessageDao.save(..))" id="pt" />
<aop:pointcut expression="execution(* com.shore.dao.impl.UserDao.save(..)) or execution(* com.shore.dao.impl.MessageDao.save(..))" id="pt" />
<!-- 且:&& and --> <!-- 语法虽然没错,但,没意义 -->
<aop:pointcut expression="execution(* com.shore.dao.impl.UserDao.save(..)) && execution(* com.shore.dao.impl.MessageDao.save(..))" id="pt" />
<aop:pointcut expression="execution(* com.shore.dao.impl.UserDao.save(..)) and execution(* com.shore.dao.impl.MessageDao.save(..))" id="pt" />
<!-- 【7、取非值:not ! 不拦截指定的规则,拦截除此之外的所有类的方法】 -->
<aop:pointcut expression="!execution(* com.shore.dao.impl.UserDao.save(..))" id="pt"/>
<!-- 注意not前必须有空格 -->
<aop:pointcut expression=" not execution(* com.shore.dao.impl.UserDao.save(..))" id="pt"/>
2、实例
用到的jar包:

相关代码:
//接口
public interface IUserDao {
public void save();
} //接口实现类
public class UserDao implements IUserDao { @Override
public void save() { //3、执行业务方法
System.out.println("3、保存用户成功!");
}
}
MessageDao 类(此类,没有实现任何接口)
public class MessageDao {
public void save() { //3、执行业务方法
System.out.println("3、保存信息成功!");
}
}
Aop 类
package com.shore.aop; import org.aspectj.lang.ProceedingJoinPoint; /**
* @author DSHORE/2019-11-7
*
*/
public class Aop {
//around:环绕; ProceedingJoinPoint:必须添加(执行)
@SuppressWarnings("unused")
private void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("2、环绕前....");
pjp.proceed(); // 执行目标方法(业务代码)
System.out.println("5、环绕后....");
} public void begin() {
System.out.println("1、开启事务......");
} public void commit() {
System.out.println("6、提交事务......");
} public void afterReturning() {
System.out.println("4、afterReturning(),返回消息");
} //有异常,执行这个第四步;没有异常,则执行上面的第四步
public void afterThrowing(){
System.out.println("4、afterThrowing(),返回异常消息");
}
}
Spring 配置文件(beans.xml)
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- dao类 -->
<bean id="userDao" class="com.shore.dao.impl.UserDao"></bean>
<bean id="messageDao" class="com.shore.dao.impl.MessageDao"></bean> <!-- 注入切面类 -->
<bean id="aop" class="com.shore.aop.Aop"></bean> <aop:config>
<!-- 配置切入点 -->
<!-- 切入点表达式语法: -->
<!-- 【1、拦截所有public方法】 --> <!-- 【第一个*是返回类型,第二个*是方法名 -->
<!-- <aop:pointcut expression="execution(public * *(..))" id="pt" /> --> <!-- 【2、拦截所有save开头的方法】 -->
<!-- <aop:pointcut expression="execution(* save(..))" id="pt" /> --> <!-- 【3、拦截指定类的指定方法, 拦截时候一定要定位到方法】 -->
<!-- <aop:pointcut expression="execution(* com.shore.dao.impl.UserDao.save(..))" id="pt" /> --> <!-- 【4、拦截指定类的所有方法】 -->
<!-- <aop:pointcut expression="execution(* com.shore.dao.impl.UserDao.*(..))" id="pt" /> --> <!-- 【5、拦截指定包,以及其自包下所有类的所有方法】 -->
<!-- <aop:pointcut expression="execution(* com..*.*(..))" id="pt" /> -->
<!-- <aop:pointcut expression="execution(* com..UserDao.*(..))" id="pt" /> --> <!-- 6、多条件 -->
<!-- 【(1)或:or ||】 -->
<!-- <aop:pointcut expression="execution(* com.shore.dao.impl.UserDao.save(..)) or execution(* com.shore.dao.impl.MessageDao.save(..))" id="pt" /> -->
<!-- 【(2)与:and &&】 -->
<aop:pointcut expression="execution(* com.shore.dao.impl.UserDao.save(..)) and execution(* com.shore.dao.impl.MessageDao.save(..))" id="pt" /> <!-- 【7、否定:! not(not前后都需要空格)】 -->
<!-- <aop:pointcut expression="!execution(* com.shore.dao.impl.UserDao.*(..))" id="pt" /> -->
<aop:pointcut expression=" not execution(* com.shore.dao.impl.UserDao.*(..))" id="pt" /> <!-- 配置切面(切入点形成的类,切入点就是重复的代码/方法) -->
<aop:aspect ref="aop">
<!-- 1、开启事务。。。。。。 -->
<aop:before method="begin" pointcut-ref="pt" />
<!-- 6、提交事务 -->
<aop:after method="commit" pointcut-ref="pt" />
<!-- 环绕2/5 -->
<aop:around method="around" pointcut-ref="pt" />
<!-- 4、afterReturning -->
<aop:after-returning method="afterReturning"
pointcut-ref="pt" />
<!-- 4、异常(程序出现异常,执行这个第四步;没有异常,则执行上面的第四步) -->
<aop:after-throwing method="afterThrowing"
pointcut-ref="pt" />
</aop:aspect>
</aop:config>
</beans>
测试类
package com.shore.test; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.shore.dao.IUserDao;
import com.shore.dao.impl.MessageDao; /**
* @author DSHORE/2019-11-7
*
*/
public class MyTest {
@Test
public void testUserDao() {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
IUserDao userDao = (IUserDao) context.getBean("userDao");
//$Proxy4 :class com.sun.proxy.$Proxy4
System.out.println("这个相当于动态代理$Proxy4:"+userDao);//返回值:com.shore.dao.impl.UserDao@73aecc3a
userDao.save();
System.out.println("=============== 分割线 ==============="); MessageDao messageDao = (MessageDao) context.getBean("messageDao");
System.out.println("这个相当于Cglib子类代理:"+messageDao);//返回值:com.shore.dao.impl.MessageDao@15412e75
messageDao.save();
}
}
上方实例,切入点出代码,详细解析:
1、拦截所有public方法
<!-- 【1、拦截所有public方法】 --> <!-- 第一个*是返回值类型,第二个*是方法名;两个..表示可以是两个或者是多个参数 -->
<aop:pointcut expression="execution(public * *(..))" id="pt" />
运行结果图:

解析:
从上面的项目截图以及相关代码,可以看出:只有三个public 方法,Aop类中的不算,因为他是切面类。故,上面红框中的结果,大家不难理解。没有红框的两处代码,是对IUserDao类进行拦截,输出两遍,是因为测试类,调用它两遍。
2、拦截所有save开头的方法
<!-- 【2、拦截所有save开头的方法】 --> <!-- 第一个*是返回类型,两个..表示可以是两个或者是多个参数 -->
<aop:pointcut expression="execution(* save(..))" id="pt" />
运行结果图:

解析省略(看结果图中的红色文字)
3、拦截指定类的指定方法, 拦截时候一定要 定位到方法
<!-- 【3、拦截指定类的指定方法, 拦截时候一定要定位到方法】 --> <!-- 第一个*是返回类型,两个..表示可以是两个或者是多个参数 -->
<aop:pointcut expression="execution(* com.shore.dao.impl.UserDao.save(..))" id="pt" />
运行结果图:

解析:
从上面的代码和结果图,可以看出,这里只对UserDao类中的save方法进行拦截。虽然MessageDao类中的save方法也运行了,但是,没有开启事务,也没提交事务,故不会生效。
4、拦截指定类的所有方法
<!-- 【4、拦截指定类的所有方法】 --> <!-- 第一个*是返回值类型,第二个*是方法名;两个..表示可以是两个或者是多个参数 -->
<aop:pointcut expression="execution(* com.shore.dao.impl.UserDao.*(..))" id="pt" />
运行结果图:

解析省略(和上面第3点一样,UserDao类中,有多少个方法,就执行多少个,结果类似)
5、拦截指定包,以及其自包下所有类的所有方法
<!-- 【5、拦截指定包,以及其自包下所有类的所有方法】 -->
<aop:pointcut expression="execution(* com..*.*(..))" id="pt" /><!-- 这几个*分别是 返回类型、com包下的所有类、指定类下的所有方法 -->
<aop:pointcut expression="execution(* com..UserDao.*(..))" id="pt" />
运行结果图:


解析省略(和上面的测试结果类似)
6、多条件
<!-- 6、多条件 -->
<!-- 【(1)或:or ||】 -->
<aop:pointcut expression="execution(* com.shore.dao.impl.UserDao.save(..)) or execution(* com.shore.dao.impl.MessageDao.save(..))" id="pt" />
<!-- 【(2)与:and &&】 -->
<aop:pointcut expression="execution(* com.shore.dao.impl.UserDao.save(..)) and execution(* com.shore.dao.impl.MessageDao.save(..))" id="pt" />
运行结果图:


解析省略(看结果图中的红色文字)
7、否定: ! not(注意:not前后都需要空格)
<!-- 【7、否定: ! not(not前后都需要空格)】 -->
<aop:pointcut expression="!execution(* com.shore.dao.impl.UserDao.*(..))" id="pt" />
<aop:pointcut expression=" not execution(* com.shore.dao.impl.UserDao.*(..))" id="pt" />
运行结果图:

解析省略(看结果图中的红色文字)
本文总结: 经测试结果显示,做修饰符(public/private/protected)和否定(! not)测试时,连接口类都一起拦截。除这两种以外,只要是指定了包名、类名、方法名的 等等,都不会再去拦截接口类。
|
原创作者:DSHORE 作者主页:http://www.cnblogs.com/dshore123/ 原文出自:https://www.cnblogs.com/dshore123/p/11823849.html 欢迎转载,转载务必说明出处。(如果本文对您有帮助,可以点击一下右下角的 推荐,或评论,谢谢!) |
Java进阶知识22 Spring execution 切入点表达式的更多相关文章
- Java进阶知识25 Spring与Hibernate整合到一起
1.概述 1.1.Spring与Hibernate整合关键点 1) Hibernate的SessionFactory对象交给Spring创建. 2) hibernate事务交给spring的声明 ...
- Java进阶知识24 Spring的事务管理(事务回滚)
1.事务控制概述 1.1.编程式事务控制 自己手动控制事务,就叫做编程式事务控制. Jdbc代码: connection.setAutoCommit(false); ...
- Java进阶知识21 Spring的AOP编程
1.概述 Aop:(Aspect Oriented Programming)面向切面编程 功能: 让关注点代码与业务代码分离! 关注点:重复代码就叫做关注点:切面: 关注点形成的类, ...
- Java进阶知识23 Spring对JDBC的支持
1.最主要的代码 Spring 配置文件(beans.xml) <!-- 连接池 --> <bean id="dataSource" class="co ...
- Java进阶知识20 Spring的代理模式
本文知识点(目录): 1.概念 2.代理模式 2.1.静态代理 2.2.动态代理 2.3.Cglib子类代理 1.概念 1.工厂模式 2. 单例模式 代理(Proxy ...
- Java进阶知识17 Spring Bean对象的创建细节和创建方式
本文知识点(目录): 1.创建细节 1) 对象创建: 单例/多例 2) 什么时候创建? 3)是否延迟创建(懒加载) 4) 创建对象之后, ...
- Java进阶知识15 Spring的基础配置详解
1.SSH各个的职责 Struts2:是web框架(管理jsp.action.actionform等).Hibernate:是ORM框架,处于持久层.Spring:是一个容器框架,用于配置bean,并 ...
- Java进阶知识18 Spring对象依赖关系的几种写法
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- Java进阶知识16 Spring创建IOC容器的两种方式
1.直接得到 IOC 容器对象 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("app ...
随机推荐
- css 清除浮动 & BFC
前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! 文档流的概念:html 中 block 块元素默认是单独占据一行的,从上到下排列,也就是我们说的文档流. ...
- PAT-1014 Waiting in Line (30 分) 优先队列
Suppose a bank has N windows open for service. There is a yellow line in front of the windows which ...
- (九)mybatis之延迟加载
一.为什么要使用延迟加载? 使用延迟加载的意义 在进行数据查询时,为了提高数据库查询性能,尽量使用单表查询,因为单表查询比多表关联查询速度快. 如果查询单表就可以满足需求,一开始先查询单表,当需要关联 ...
- (一)mybatis介绍
一.mybatis简介 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...
- Abp 领域事件简单实践 <一>
领域事件,是领域内发生的事件引发别的操作,其他的类可以订阅这是事件. 接着上一篇,在testOrder 上实现一个接口 IEventHandler<EntityCreatingEventDat ...
- 基于【 centos7】一 || 安装ELK
一.安装jdk 上传安装包并解压:tar -zxvf ... 配置环境变量: 在配置文件中添加如下配置信息:vi /etc/profile export JAVA_HOME=/usr/local/jd ...
- vue+element下拉树选择器
项目需求:输入框点击弹出树形下拉结构,可多选或者单选. 解决方案:1.使用layui formSelect多选插件 2.基于vue+elementui 下拉框和树形控件组合成树形下拉结构 <el ...
- numpy相关使用
相关学习资料 : numpy中文网 https://www.numpy.org.cn/ 1 numpy索引区间为左闭右开,第一个索引能取到,第二个索引取不到 索引内可加步长 如 import nump ...
- ORACLE 存储过程提高
1.SQLCODE和SQLERRM 2.%TYPE和%ROWTYPE的使用 3.sql%rowcount的作用 1.SQLCODE和SQLERRM SQLCode:数据库操作的返回码,其中 --成功: ...
- asp.net mvc 防止跨站攻击
View @using (Html.BeginForm("Contact","Home",FormMethod.Post)) { @Html.AntiForge ...