文章目录

  • 概述
  • 切点表达式函数
    • 方法切点函数
      • execution()
      • @annotation()
    • 方法入参切点函数
      • args()
      • @args()
    • 目标类切点函数
      • within()
      • target()
      • @within()
      • @target()
    • 代理类切点函数
      • this
    • 注意事项
  • 在函数入参中使用通配符
    • `*`
    • `..`
    • `+`
  • 逻辑运算符
    • &&
    • ||
  • 不同增强类型
    • @Before
    • @AfterReturning
    • @Around
    • @AfterThrowing
    • @After
    • @DeclareParents
  • 引介增强用法

概述

@AspectJ使用Java5.0注解和正规的AspectJ的切点表达式语言描述切面, 由于Spring只支持方法的连接点,所以Spring仅支持部分AspectJ的切点语言。

下文阐述的AspectJ切点表达式语言,以AspectJ5.0版本为准。


切点表达式函数

AspectJ5.0的切点表达式由关键字操作参数组成.

比如 execution(* greetTo(..)) , execution为关键字, * greetTo(..) 为操作参数。

在这里execution代表目标类执行某一方法,而 * greetTo(…)描述目标方法的匹配模式串,二者联合起来标识目标类greetTo()方法的连接点。 为了方便描述,将execution()称为函数,而将匹配串 * greetTo(..)称作函数的入参。

Spring支持9个@AspectJ切点表达式函数,它们用不同的方式描述目标类的连接点
根据描述对象的不同,大致可以分为4类

  • 方法切点函数:通过描述目标类方法的信息定义连接点

  • 方法入参切点函数:通过描述目标类方法入参的信息定义连接点

  • 目标类切点函数:通过描述目标类类型的信息定义连接点

  • 代理类切点函数:通过描述目标类的代理类的信息定义连接点

下面我们来看下具体的函数

方法切点函数

execution()

入参:方法匹配模式串

说明:表示满足某一匹配模式的所有目标类方法连接点,如 execution(* greetTo(…))表示所有目标类中的greetTo()方法,greetTo()方法可以带带任意的入参和任意的返回值


@annotation()

入参:方法注解类名

说明:表示标注了某特定注解的目标类方法连接点, 比如@annotation(com.xgj.annotation.NeedTest)表示任何标注了@NeedTest注解的目标类方法。


方法入参切点函数

args()

入参:类名

说明:通过判断目标类方法运行时入参对象的类型定义指定连接点,如args(com.xgj.Waiter)表示所有有且仅有一个按类型匹配于Waiter入参的方法。


@args()

入参:类型注解类型

说明:通过判断目标类方法运行时入参对象的类是否标注了特定的注解指定连接点。 比如@args(com.xgj.Monitor)表示任何这样的一个目标方法,它有一个入参且入参对象的类标注@Monitor注解


目标类切点函数

within()

入参:类名匹配串

说明:表示特定域下的所有连接点,比如 within(com.xgj.service.*)表示com.xgj.service包中所有的连接点,即包中所有类的所有方法; 而 within(com.xgj.service.*Service)表示在com.xgj.service包中所有以Service结尾的类的所有连接点


target()

入参:类名

说明:假如目标类按类型匹配与指定类,则目标类的所有连接点匹配这个切点。 比如通过target(com.xgj.Waiter)定义的切点,Waiter及Waiter实现类NaiveWaiter中的所有连接点都匹配该切点


@within()

入参:类型注解类名

说明:假如目标类按类型匹配于某个类A,且类A标注了特定的注解,这目标类的所有连接点匹配这个切点。 比如@within(com.xgj.Monitor)定义的切点,加入Waiter实现了@Monitor注解,这Waiter及Waiter的实现类NaiveWaiter的说哟连接点都匹配这个切点


@target()

入参:类型注解类名

说明:假如目标类标注了特定注解,则目标类的所有连接点都匹配该切点。 如@target(com.xgj.Monitor),假设NaiveWaiter标注了@Monitor注解,则NaiveWaiter的所有连接点都匹配这个切点


代理类切点函数

this

入参:类名

说明:代理类按类型匹配于指定类,则被代理的目标类的所有连接点都匹配该切点。

注意事项

除了上述的函数外,@AspectJ还有其它的函数 ,比如call()、initialization()等,但是不能够在Spring中使用,否则会抛出IllegalArgumentException异常。


在函数入参中使用通配符

有些函数的入参可以接受通配符,@AspectJ支持三种通配符

*

* 表示匹配任意字符,但它只能匹配上下文中的一个元素


..

..表示匹配任意字符,可以匹配上下文中的 多个元素, 但在标识类时,必须和 * 联合使用,而在表示入参时则单独使用


+

+表示按照类型匹配指定类的所有类,必须跟在类名后面,比如com.xgj.Service+。 继承或扩展指定类的所有类,同时还包含指定类本身。

##支持通配符的函数说明

  • 支持所有通配符 execution()和within() , 比如within(com.xgj.*) within(com.xgj.service..*.*Service+)

  • 仅支持“+”通配符: args()、this()和target(). 比如args(com.xgj.Waiter+) 、target(java.util.List+)等。 虽然支持+通配符,但是意义不大。 对于这些函数来讲使用+和不使用+是等价的

  • 不支持通配符: @args()、@within、@target 和 @annotation.

此外,args() this() target() @args() @within() @target() @annotation() 这7个函数除了可以指定类名外,也可以指定变量名,并将目标对象中的变量绑定到增强的方法中。


逻辑运算符

切点表达式由切点函数组成,切点函数之间可以进行逻辑运算,组成复合切点。

Spring支持以下切点运算符

&&

与操作符,相当于切点的交集运算。

如果在Spring的XML配置文件中使用切点表达式,由于&是XML特殊字符,所以使用转义字符串&&表示。

为了方便,Spring提供了一个等效的运算符and, 比如within(com.xgj..*) and args(String) 表示在com.xgj包下所有类(当前包以及子孙包)拥有一个String入参的方法;


||

或操作符,相当于切点的并集运算,or是等效的操作符。如within(com.xgj..*) || args(String) 表示在com.xgj包下的所有类的方法,或者所有拥有一个String入参的方法;


非操作符,相当于切点的反集运算,not是等效的操作符。如!within(com.xgj.*) 表示所有不在com.xgj包下的方法。

注意:

在Spring中使用and or 和 not操作符时,允许不在前面添加空格,比如within(com.xgj..*)andnotargs(String)within(com.xgj..*) and not args(String)是等效的,不过为了程序的可读性,我们还是要求在操作符的前后添加空格。

另外,如果not位于切点表达式的开头,则必须在开头添加一个空格,否则会产生解析错误。 比如 not within(com.xgj..*)


不同增强类型

@AspectJ为各种的增强类型提供了不同的注解类,它们位于org.aspectj.lang.annotation.*包中,这些注解类拥有若干个成员,可以通过这些成员完成定义切点信息、绑定连接点参数等操作;

此外,这些注解的存留期限都是RetentionPolicy.RUNTIME,标注目标都是ElementType.METHOD。


@Before

前置增强,相当于BeforeAdvice的功能,

Before注解类拥有两个成员:

  • value:该成员用于定义切点;

  • argNames:由于无法通过Java反射机制获取方法入参名,所有如果在Java编译时未启动调试信息或者需要在运行期解析切点,就必须通过这个成员指定注解所标注增强方法的参数名(注意两者名字必须完全相同),多个参数名用逗号分隔。


@AfterReturning

后置增强,相当于AfterReturningAdvice,

AfterReturning注解类拥有4个成员:

  • value:该成员用于定义切点;

  • pointcut:表示切点的信息,如果显式指定pointcut值,它将覆盖value的设置值,可以将pointcut成员看成是value的同义词;

  • returning:将目标对象方法的返回值绑定给增强的方法;

  • argNames:如前所述。


@Around

环绕增强,相当于MethodInterceptor,

Around注解类拥有两个成员:

  • value:该成员用于定义切点;

  • argNames:如前所述。

@Aspect
public class AtTargetAspect {@Around("@target(com.xgj.aop.spring.advisor.aspectJ.function.attarget.Mark)")public void crossCuttingCode(ProceedingJoinPoint joinPoint)throws Throwable {System.out.println("****AtTargetAspect.crossCuttingCode() : "+ joinPoint.getSignature().getName()+ ": Before Method Execution");try {joinPoint.proceed();} finally {// Do Something useful, If you have}System.out.println("****AtTargetAspect.crossCuttingCode() : "+ joinPoint.getSignature().getName()+ ": After Method Execution");}
}

@AfterThrowing

抛出增强,相当于ThrowsAdvice.

AfterThrowing注解类拥有4个成员:

  • value:该成员用于定义切点;

  • pointcut:表示切点的信息,如果显式指定pointcut值,它将覆盖value的设置值,可以将pointcut成员看成是value的同义词;

  • throwing:将抛出的异常绑定到增强方法中;

  • argNames:如前所述。


@After

Final增强,不管是抛出异常或者是正常退出,该增强都会得到执行,该增强没有对应的增强接口,可以把它看成是ThrowsAdvice和AfterReturningAdvice的混合物,一般用于释放资源,相当于try{}finally{}的控制流。

After注解类拥有两个成员:

  • value:该成员用于定义切点;

  • argNames:如前所述。


@DeclareParents

引介增强,相当于IntroductionInterceptor,

DeclareParents注解类拥有两个成员:

  • value:该成员用于定义切点,它表示在哪个目标类上添加引介增强;

  • defaultImpl:默认的接口实现类。


引介增强用法

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

假设我们希望Waiter能够同时充当Seller的角色,即通过切面技术为NaiveWaiter新增Seller接口的实现。

下面我们使用@AspectJ的引介增强来实现这一个功能。

package com.xgj.aop.spring.advisor.aspectJ.basic;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;/*** * * @ClassName: EnableSellerAspect* * @Description: 希望Waiter也能同时充当Seller的角色* * @author: Mr.Yang* * @date: 2017年8月26日 上午1:23:41*/@Aspect
public class EnableSellerAspect {// (1)value 为NaiveWaiter添加接口实现, (2)defaultImpl默认的接口实现类@DeclareParents(value = "com.xgj.aop.spring.advisor.aspectJ.basic.NaiveWaiter", defaultImpl = SmartSeller.class)public Seller seller; // (3) 要实现的目标接口
}

分析:

在EnableSellerAspect 切面中,通过@DeclareParents为NaiveWaiter添加了一个需要实现的Seller接口,并指定其默认实现类为SmartSeller. 然后通过切面技术将SmartSeller融合到NaiveWaiter中,这样NaiveWaiter就实现了Seller接口。

配置文件,配置切面和NaiveWaiter Bean

<?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.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 使用基于Schema的aop命名空间进行配置 --><!-- 基于@AspectJ切面的驱动器 -->
<aop:aspectj-autoproxy/><!-- 目标Bean -->
<bean id="waiter" class="com.xgj.aop.spring.advisor.aspectJ.basic.NaiveWaiter"/>
<!-- 使用了@AspectJ注解的切面类 -->
<bean class="com.xgj.aop.spring.advisor.aspectJ.basic.EnableSellerAspect"/></beans>

测试类:

package com.xgj.aop.spring.advisor.aspectJ.basic;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class EnableSellerAspectTest {@Testpublic void test() {ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com/xgj/aop/spring/advisor/aspectJ/basic/conf-aspectJ.xml");Waiter waiter = ctx.getBean("waiter", Waiter.class);waiter.greetTo("XiaoGongJiang");// 可以成功的进行强制类型转换Seller seller = (Seller) waiter;seller.sell("beer", "XiaoGongJiang");}
}

运行结果:

2017-08-26 01:42:50,077  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@24b9371e: startup date [Sat Aug 26 01:42:50 BOT 2017]; root of context hierarchy
2017-08-26 01:42:50,173  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/basic/conf-aspectJ.xml]
NaiveWaiter Greet to XiaoGongJiang
SmartSeller: sell beer to XiaoGongJiang

可见,NaiveWaiter已经成功的新增了Seller接口的实现。

Spring-AOP @AspectJ语法基础相关推荐

  1. 关于 Spring AOP (AspectJ) 你该知晓的一切

    [版权申明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/54629058 出自[zejian ...

  2. Spring AOP + AspectJ Annotation Example---reference

    In this tutorial, we show you how to integrate AspectJ annotation with Spring AOP framework. In simp ...

  3. Spring AOP / AspectJ AOP 的区别?

    Spring AOP / AspectJ AOP 的区别? Spring AOP属于运行时增强,而AspectJ是编译时增强. Spring AOP基于代理(Proxying),而AspectJ基于字 ...

  4. Spring AOP,AspectJ,CGLIB 有点晕

    AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓存.对象池管理等.AOP 实现的关键就在于 ...

  5. Spring AOP AspectJ Pointcut Expressions With Examples--转

    原文地址:http://howtodoinjava.com/spring/spring-aop/writing-spring-aop-aspectj-pointcut-expressions-with ...

  6. Spring AOP AspectJ

    本文讲述使用AspectJ框架实现Spring AOP. 再重复一下Spring AOP中的三个概念, Advice:向程序内部注入的代码. Pointcut:注入Advice的位置,切入点,一般为某 ...

  7. Spring AOP AspectJ 代码实例

    本文参考来源 http://examples.javacodegeeks.com/enterprise-java/spring/aop/spring-aop-aspectj-example/ http ...

  8. 基于@AspectJ配置Spring AOP之一--转

    原文地址:http://tech.it168.com/j/2007-08-30/200708302209432.shtml 概述 在低版本Spring中定义一个切面是比较麻烦的,需要实现特定的接口,并 ...

  9. Spring AOP 和 AspectJ的区别

    Spring AOP 和 AspectJ的区别 springAOP 是spring支持的面向切面AOP 编程. AspectJ是一个面向切面的框架,它扩展了Java语言.AspectJ定义了AOP语法 ...

最新文章

  1. 拼多多面试|如何用 Redis 统计独立用户访问量?
  2. ffmpeg 如何把左右声道_耳机里的乾坤 | 左右声道?耳返?这些耳机常识,爱听音乐的你一定不会错过...
  3. 2021年衢州高考的成绩查询,2021年衢州高考状元是谁分数多少分,历年衢州高考状元名单...
  4. 在Struts2中实现文件上传(二)
  5. 目标检测之Mtcnn网络详解(人脸检测)
  6. Codeforces Round #Pi (Div. 2) B. Berland National Library 模拟
  7. 【C语言】学习笔记6——const
  8. Nginx 如何开启gzip 来提高页面加载速度
  9. udhcp源码详解(二)--转
  10. WINDOWS如何编写注册表文件
  11. react jsoneditor 的学习使用
  12. python矩阵连乘_第3章 动态规划——矩阵连乘最优计算方式查找
  13. 怎么查期刊是核心、是EI,还是SCI
  14. 高光谱知识(1)-高光谱成像技术的理解
  15. 用户抱怨苹果一体机进灰 苹果称中国环境不好
  16. 2021-10-20:分数到小数。给定两个整数,分别表示分数的分子numerator和分母denominator,以字符串形式返回小数。如果小数部分为循环小数,则将循环的部分括在括号内。输入: num
  17. html把保留图片改为提交按钮,如何制作图片按钮,并为图片按钮添加提交表单和重置表单功能...
  18. python实现账号密码登录
  19. C++ concurrentqueue资料
  20. redis简单分布式锁实现 超简单的那种

热门文章

  1. tf.arg_min
  2. python getattr调用自己模块_在Python中通过getattr获取对象引用的方法
  3. SGM:Sequence Generation Model for Multi-Label Classification(SGM)
  4. 强化学习笔记:Q_learning (Q-table)示例举例
  5. 数据中台应用实战50篇(一)-带你概览BI、数据仓库、数据湖与数据中台之间有什么关联关系?(建议收藏)
  6. linux命令行中,双引号中的感叹号将被解释为历史命令
  7. 聚类算法中各种距离的计算与python的具体实现代码
  8. 【机器学习算法-python实现】svm支持向量机(1)—理论知识介绍
  9. 【Java设计模式】策略模式
  10. spring core源码解读之ASM4用户手册翻译之一asm简介