Java Spring AOP 切点表达式开发手册

一、切点表达式详解

在Spring AOP中,切点表达式用于定义在哪些连接点(Join Point)上应用通知(Advice)。常见的切点表达式是execution表达式,其格式如下:

  • 语法: execution([修饰符] 返回类型 [包.类.方法] (参数))
    • 修饰符: 可选,指定方法的访问修饰符,如publicprivate等。
    • 返回类型: 必填,指定方法的返回类型,可用*通配任意类型。
    • 包.类.方法: 可选,指定类和方法的全限定名。*表示通配任意类或方法。
    • 参数: 必填,指定方法的参数列表,..表示任意参数。

此外,切点表达式还可以通过逻辑操作符进行组合,如&&(与)、||(或)、!(非)等,使得切点表达式更加灵活和强大。

二、常用切点表达式

  1. 拦截某个包下所有类的所有方法

    • 表达式: execution(* com.example.pointcut.*.*(..))
    • 说明: 拦截com.example.pointcut包下所有类的所有方法,方法的返回值、方法名和参数列表均可为任意类型。
  2. 拦截所有public方法

    • 表达式: execution(public * *(..))
    • 说明: 拦截所有public修饰的方法,方法的返回值和参数列表可以是任意类型。
  3. 拦截以save开头的方法

    • 表达式: execution(* save*(..))
    • 说明: 拦截所有方法名以save开头的方法,参数列表可以是任意类型。
  4. 拦截指定类的指定方法

    • 表达式: execution(public * com.example.pointcut.OrderDao.save(..))
    • 说明: 拦截com.example.pointcut.OrderDao类中的save方法,且该方法必须为public类型,参数列表可以是任意类型。
  5. 拦截指定类的所有方法

    • 表达式: execution(* com.example.pointcut.UserDao.*(..))
    • 说明: 拦截com.example.pointcut.UserDao类中的所有方法,方法的返回值和参数列表可以是任意类型。
  6. 拦截指定包及其子包下所有类的所有方法

    • 表达式: execution(* com.example..*.*(..))
    • 说明: 拦截com.example包及其所有子包下的所有类的所有方法,方法的返回值和参数列表可以是任意类型。
  7. 多个表达式的组合使用

    • 或 (OR): execution(* com.example.pointcut.UserDao.save()) || execution(* com.example.pointcut.OrderDao.save())
    • 与 (AND): execution(* com.example.pointcut.UserDao.save()) && execution(* com.example.pointcut.OrderDao.save())
    • 非 (NOT): !execution(* com.example.pointcut.OrderDao.save())

三、综合案例

为了全面演示切点表达式的使用,我们将结合一个综合案例展示如何在实际项目中应用上述表达式。

1. 项目背景

假设你正在开发一个包含用户管理和订单管理模块的业务系统,涉及到UserDaoOrderDao两个数据访问对象,以及UserServiceOrderService两个业务逻辑对象。

  • UserDao: 负责用户的增删改查操作。
  • OrderDao: 负责订单的增删改查操作。
  • UserService: 提供用户管理的业务逻辑。
  • OrderService: 提供订单管理的业务逻辑。

2. 实现代码

package com.example.pointcut;

public class UserDao {
    public void saveUser() {
        System.out.println("Saving user");
    }

    public void deleteUser() {
        System.out.println("Deleting user");
    }
}

public class OrderDao {
    public void saveOrder() {
        System.out.println("Saving order");
    }

    public void cancelOrder() {
        System.out.println("Cancelling order");
    }
}

public class UserService {
    public void addUser() {
        System.out.println("Adding a user");
    }

    public void deleteUser() {
        System.out.println("Deleting a user");
    }
}

public class OrderService {
    public void placeOrder() {
        System.out.println("Placing an order");
    }

    public void cancelOrder() {
        System.out.println("Cancelling an order");
    }
}

3. 切点表达式配置

<aop:config>
    <!-- 拦截com.example.pointcut包下所有类的所有方法 -->
    <aop:pointcut expression="execution(* com.example.pointcut.*.*(..))" id="allMethodsInPackage"/>

    <!-- 拦截所有public方法 -->
    <aop:pointcut expression="execution(public * *(..))" id="allPublicMethods"/>

    <!-- 拦截以save开头的方法 -->
    <aop:pointcut expression="execution(* save*(..))" id="saveMethods"/>

    <!-- 拦截指定类的指定方法 -->
    <aop:pointcut expression="execution(public * com.example.pointcut.OrderDao.save(..))" id="orderSaveMethod"/>

    <!-- 拦截指定类的所有方法 -->
    <aop:pointcut expression="execution(* com.example.pointcut.UserDao.*(..))" id="userDaoMethods"/>

    <!-- 拦截指定包及其子包下所有类的所有方法 -->
    <aop:pointcut expression="execution(* com.example..*.*(..))" id="allMethodsInPackageAndSubpackages"/>

    <!-- 组合表达式:拦截UserDao和OrderDao中的save方法 -->
    <aop:pointcut expression="execution(* com.example.pointcut.UserDao.save(..)) || execution(* com.example.pointcut.OrderDao.save(..))" id="saveMethodsInUserAndOrder"/>

    <!-- 组合表达式:排除OrderDao中的save方法 -->
    <aop:pointcut expression="!execution(* com.example.pointcut.OrderDao.save(..))" id="notOrderSave"/>

    <!-- 为每个切点配置Advice -->
    <aop:advisor advice-ref="loggingAdvice" pointcut-ref="allMethodsInPackage"/>
    <aop:advisor advice-ref="loggingAdvice" pointcut-ref="allPublicMethods"/>
    <aop:advisor advice-ref="loggingAdvice" pointcut-ref="saveMethods"/>
    <aop:advisor advice-ref="loggingAdvice" pointcut-ref="orderSaveMethod"/>
    <aop:advisor advice-ref="loggingAdvice" pointcut-ref="userDaoMethods"/>
    <aop:advisor advice-ref="loggingAdvice" pointcut-ref="allMethodsInPackageAndSubpackages"/>
    <aop:advisor advice-ref="loggingAdvice" pointcut-ref="saveMethodsInUserAndOrder"/>
    <aop:advisor advice-ref="loggingAdvice" pointcut-ref="notOrderSave"/>
</aop:config>

4. 解释与运行结果

  • 所有方法切入: 配置allMethodsInPackage会拦截com.example.pointcut包下的UserDaoOrderDao中的所有方法,如saveUserdeleteUsersaveOrdercancelOrder
  • 拦截public方法: allPublicMethods会拦截所有public修饰的方法,这包括了所有的公开方法。
  • 拦截以save开头的方法: saveMethods拦截了saveUsersaveOrder等方法。
  • 拦截指定类的指定方法: orderSaveMethod仅拦截OrderDao中的saveOrder方法。
  • 拦截指定类的所有方法: userDaoMethods拦截了UserDao类中的saveUserdeleteUser方法。
  • 组合表达式:
    • saveMethodsInUserAndOrder拦截了UserDaoOrderDao中的save方法。
    • notOrderSave排除了OrderDao中的saveOrder方法,其余方法依然会被拦截。

四、总结

通过这个综合案例,我们详细展示了如何使用Spring AOP的切点表达式来控制应用程序中的方法拦截。理解这些表达式并灵活运用它们,可以极大地提高代码的可维护性和可扩展性。通过组合和排除规则,你可以精确地控制哪些方法需要增强,哪些不需要,从而实现如日志记录、权限校验、事务管理等典型的AOP应用场景。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值