0、前情回顾
什么是动态代理,Spring动态代理的基本实现参考:https://www.yusian.com/blog/?p=1981
动态代理中比较重要的一个环节就是AOP组装,将附加方法与原始方法进行组合,那哪些原始方法需要进行组装呢?如何匹配原始方法,这便是切入点表达式需要解决的问题;
回顾一下动态代理中Spring配置文件的内容:
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="userService" class="com.yusian.service.UserServiceImpl"/>
<bean id="before" class="com.yusian.aop.Before"/>
<aop:config>
<aop:pointcut id="pc" expression="execution(* *(..))"/>
<aop:advisor advice-ref="before" pointcut-ref="pc"/>
</aop:config>
</beans>
其中<aop:pointcut id="pc" expression="execution(* *(..))"/>
即定义切入点,expression的值决定了哪些方法将会被配置执行,准确的说实际匹配的是哪些类的哪些方法
1、切入点函数
execution()
基本格式如:execution(* *(..))
,execution函数参数包含三个部分:返回值、对象方法名、参数列表;
- 配置所有:
* *(..)
所有返回值类型,所有对象及方法,任意类型参数; -
配置参数:
* *(..)
任意类型参数,* *(String, String)
两个String类型参数的方法; -
配置对象方法名:
所有对象的所有方法 <aop:pointcut id="pc" expression="execution(* *(..))" /> 所有对象的login方法 <aop:pointcut id="pc" expression="execution(* login(..))"/> UserServiceImpl下的所有方法 <aop:pointcut id="pc" expression="execution(* com.yusian.service.UserServiceImpl.*(..))"/> service包下的所有类的所有方法 <aop:pointcut id="pc" expression="execution(* com.yusian.service.*.*(..))"/> 所有包下UserServiceImpl的所有方法,忽略包层级使用.. <aop:pointcut id="pc" expression="execution(* *..UserServiceImpl.*(..))"/>
- 配置返回值类型:
* *(..)
任意返回值类型,boolean *(..)
返回值类型为boolean的对象方法
args()
原则上execution()
函数可以配置所有情况,属于通配函数,但使用有点繁琐,args()
可以理解为对execution
函数某些情形的封装,即只关心参数,不关心返回值类型与对象方法;
所有对象的所有方法
<aop:pointcut id="pc" expression="args(..)"/>
所有对象包含一个String类型参数的方法
<aop:pointcut id="pc" expression="args(String)"/>
within()
与args
类似,within不关心返回值或参数,只关心类与包
所有对象的所有方法
<aop:pointcut id="pc" expression="within(*)"/>
UserServiceImpl对象的所有方法
<aop:pointcut id="pc" expression="within(*..UserServiceImpl)"/>
service包下的所有类的所有方法
<aop:pointcut id="pc" expression="within(*..service.*)"/>
@annotation()
@annotaion
函数即匹配带有某个特定注解的方法
所有带有@Log注解的方法
<aop:pointcut id="pc" expression="@annotation(com.yusian.annotaion.Log)"/>
2、切入点函数逻辑运算
将以上切入点函数进行多个配合使用
service包下所有类中,带有String参数的所有方法
<aop:pointcut id="pc" expression="args(String) and within(com.yusian.service.*)"/>