Spring-AOP @AspectJ切点函数之execution()

简介: Spring-AOP @AspectJ切点函数之execution()

概述


execution()是最常用的切点函数,语法如下

execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)


其中:返回类型模式、方法名模式、参数模式是必选项。


通过execution()定义切点的不同方式


下面我们通过各种实例来理解如何使用execution()


通过方法签名定义切点


  • execution(public * *(..)) 匹配所有目标类的public方法。 第一个*代表返回类型,第二个*代表方法名,而..代表任意入参的方法
  • execution(* *To(..)) 匹配目标类所有以To为后缀的方法。 第一个*代表返回类型,而*To代表任意以To为后缀的方法。

通过类定义切点


execution(* com.xgj.aop.spring.advisor.aspectJ.function.execution.classpoint.Cleaner.*(..))匹配Cleaner接口的所有方法(包括实现类中覆写的方法), 第一个 * 代表返回任意类型 ,...Cleaner.*代表Cleaner接口中的所有方法


execution(* com.xgj.aop.spring.advisor.aspectJ.function.execution.classpoint.Cleaner.*(..))匹配Cleaner接口及其所有实现类的方法,不但匹配实现类中覆写的方法,也包括实现类中不在接口中定义的方法


通过类包定义切点


在类名模式串中,.*表示包下的所有类,..*表示包、子孙包下的所有类


execution(* com.xgj.*(..))匹配com.xgj包下所有类的所有方法


execution(* com.xgj..*(..))匹配com.xgj包、子孙包下所有类的所有方法.比如 com.xgj.dao ,com.xgj.service,com.xgj.dao.user包下所有类的所有方法都匹配。 当 ..出现在类名中时,必须后面跟*表示子孙包下的所有类。


execution(* com..*Dao.find*(..))匹配包名前缀为com的任何包下类名后缀为Dao的方法,方法名必须以find为前缀, 比如com.xgj.UserDao#findUserById()方法都是匹配切点。


通过方法入参定义切点


切点表达式中的方法入参部分比较复杂,可以使用*..通配符。 其中 *表示任意参数类型的参数, 而..表示任意类型的参数且参数个数不限。


execution(* joke(String,int))匹配joke(String,int)方法,且joke方法的第一个入参是String,第二个入参是int。 比如 匹配 SmartSeller#joke(String ,int)方法。 如果方法中的入参类型是java.lang包下的,这可以直接使用类名,否则必须使用全限定类名,比如 joke(java.util.List,int)


execution(* joke(String,*))匹配目标类中的joke()方法,该方法第一个入参为String,第二个入参为任意类型。 比如 joke(String s1, String s2)和joke(String s1,double d)都匹配,但是 joke(String s1, String s2,double d3)不匹配


execution(* joke(String,..))匹配目标类中的joke方法,该方法的第一个入参为String,后面可以有任意个入参且入参类型不限。 比如 joke(String s1),joke(String s1,String s2)和joke(String s1,double d2,String s3)都匹配。


execution(* joke(Object+))匹配目标类中的joke()方法,方法拥有一个入参,且入参是Object类型或该类的子类。 它匹配joke(String s1) 和joke(Client c) . 如果定义的切点是execution(* joke(Object)) ,则只匹配joke(Object object)而不匹配joke(String s1) 或者joke(Client c)


实例


代码已托管到Github—> https://github.com/yangshangwei/SpringMaster


仅以通过方法签名定义切点为例子,其余场景请参考https://github.com/yangshangwei/SpringMaster, 亲测通过。


execution(* com.xgj.aop.spring.advisor.aspectJ.function.execution.classpoint.Cleaner.*(..))


aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTcwODI5MTE1OTEzMTc1.png

package com.xgj.aop.spring.advisor.aspectJ.function.execution;
public class NaiveWaiter {
  /**
   * public方法,演示execution(public * *(..)),能匹配到
   */
  public void greetTo(String clientName) {
    System.out.println("NaiveWaiter greet to " + clientName);
  }
}
package com.xgj.aop.spring.advisor.aspectJ.function.execution;
public class SmartSeller {
  /**
   * public方法,演示execution(public * *(..)),能匹配到
   */
  public void sell(String goods) {
    System.out.println("SmartSeller sells " + goods);
  }
  /**
   * 
   * 
   * @Title: smileTo
   * 
   * @Description: 非public方法,演示execution(public * *(..)),不能匹配到
   * 
   * @param clientName
   * 
   * @return: void
   */
  protected void smileTo(String clientName) {
    System.out.println("SmartSeller simles to " + clientName);
  }
}

切面

package com.xgj.aop.spring.advisor.aspectJ.function.execution;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
/**
 * 
 * 
 * @ClassName: ExecutionPublicAspect
 * 
 * @Description: TODO
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年8月27日 下午1:47:55
 */
@Aspect
public class ExecutionPublicAspect {
  @Before("execution(public * *(..))")
  public void crossCuttingLogic() {
    System.out.println("织入前置增强,横切逻辑code");
  }
}


配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:aop="http://www.springframework.org/schema/aop"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 使用基于Schema的aop命名空间进行配置 -->
<!-- 基于@AspectJ切面的驱动器 -->
<aop:aspectj-autoproxy/>
<!-- 目标Bean -->
<bean id="smartSeller" class="com.xgj.aop.spring.advisor.aspectJ.function.execution.SmartSeller"/>
<bean id="naiveWaiter" class="com.xgj.aop.spring.advisor.aspectJ.function.execution.NaiveWaiter"/>
<!-- 使用了@AspectJ注解的切面类 -->
<bean class="com.xgj.aop.spring.advisor.aspectJ.function.execution.ExecutionPublicAspect"/>
</beans>


测试类

package com.xgj.aop.spring.advisor.aspectJ.function.execution;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * 
 * 
 * @ClassName: ExecutionPublicAspectTest
 * 
 * @Description: execution(public * *(..)) 测试类
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年8月27日 下午1:52:25
 */
public class ExecutionPublicAspectTest {
  @Test
  public void test() {
    ApplicationContext ctx = new ClassPathXmlApplicationContext(
        "com/xgj/aop/spring/advisor/aspectJ/function/execution/conf-execution.xml");
    SmartSeller smartSeller = (SmartSeller) ctx.getBean("smartSeller");
    // sell方法是public,会织入前置增强中的横切逻辑
    smartSeller.sell("bread");
    // smileTo方法是protec,不会织入前置增强中的横切逻辑
    smartSeller.smileTo("XiaoGongJiang");
    NaiveWaiter naiveWaiter = (NaiveWaiter) ctx.getBean("naiveWaiter");
    // greetTo方法是public,会织入前置增强中的横切逻辑
    naiveWaiter.greetTo("XiaoGongJiang");
  }
}


运行结果

2017-08-29 00:00:39,395  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@24b9371e: startup date [Tue Aug 29 00:00:39 BOT 2017]; root of context hierarchy
2017-08-29 00:00:39,514  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/function/execution/conf-execution.xml]
织入前置增强,横切逻辑code
SmartSeller sells bread
SmartSeller simles to XiaoGongJiang
织入前置增强,横切逻辑code
NaiveWaiter greet to XiaoGongJiang


相关文章
|
8月前
|
XML Java API
Spring AOP切点和通知机制的深度解析
Spring AOP切点和通知机制的深度解析
101 4
|
8月前
|
Java Serverless 应用服务中间件
Serverless 应用引擎产品使用合集之Web函数启动的Spring Boot项目可以通过什么方式配置Nginx
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
8月前
|
XML 缓存 Java
浅浅了解下Spring中生命周期函数(Spring6全攻略)
Spring框架设计生命周期回调函数的主要目的是为了提供一种机制,使开发人员能够在对象创建、初始化和销毁等生命周期阶段执行特定的操作。这种机制可以帮助开发人员编写更加灵活和可维护的代码。
52 0
|
9月前
|
Java 开发者 Spring
Spring AOP的切点是通过使用AspectJ的切点表达式语言来定义的。
【5月更文挑战第1天】Spring AOP的切点是通过使用AspectJ的切点表达式语言来定义的。
90 5
|
9月前
|
监控 Java 测试技术
Spring Boot与事务钩子函数:概念与实战
【4月更文挑战第29天】在复杂的业务逻辑中,事务管理是确保数据一致性和完整性的关键。Spring Boot提供了强大的事务管理机制,其中事务钩子函数(Transaction Hooks)允许开发者在事务的不同阶段插入自定义逻辑。本篇博客将详细探讨事务钩子函数的概念及其在Spring Boot中的应用。
204 1
|
9月前
|
XML Java 数据格式
spring AOP切入点execution表达式
spring AOP切入点execution表达式
121 1
|
9月前
Spring5源码(31)-基于@AspectJ的AOP
Spring5源码(31)-基于@AspectJ的AOP
70 0
|
9月前
|
XML Java 数据格式
Spring-AOP @AspectJ语法基础
Spring-AOP @AspectJ语法基础
96 0
|
消息中间件 Java Kafka
Spring 事务的独门绝技:钩子函数的使用技巧
经过前面对Spring AOP、事务的总结,我们已经对它们有了一个比较感性的认知了。今天,我继续安利一个独门绝技:Spring 事务的钩子函数。单纯的讲技术可能比较枯燥乏味。接下来,我将以一个实际的案例来描述Spring事务钩子函数的正确使用姿势。
Spring 事务的独门绝技:钩子函数的使用技巧
|
27天前
|
XML Java 应用服务中间件
Spring Boot 两种部署到服务器的方式
本文介绍了Spring Boot项目的两种部署方式:jar包和war包。Jar包方式使用内置Tomcat,只需配置JDK 1.8及以上环境,通过`nohup java -jar`命令后台运行,并开放服务器端口即可访问。War包则需将项目打包后放入外部Tomcat的webapps目录,修改启动类继承`SpringBootServletInitializer`并调整pom.xml中的打包类型为war,最后启动Tomcat访问应用。两者各有优劣,jar包更简单便捷,而war包适合传统部署场景。需要注意的是,war包部署时,内置Tomcat的端口配置不会生效。
200 17
Spring Boot 两种部署到服务器的方式