Spring动态代理中切入点表达式的基本使用

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.*)"/>

Leave a Reply