AOP中注解参数详解
基于SpringBoot、AOP与自定义注解转义字典值

基于SpringBoot、AOP与⾃定义注解转义字典值 ⼀直以来,前端展⽰字典⼀般以中⽂展⽰为主,若在表中存字典值中⽂,当字典表更改字典值对应的中⽂,会造成数据不⼀致,为此设置冗余字段并⾮最优⽅案,若由前端⾃⼰写死转义,不够灵活,若在业务代码转义,臃肿也不够通⽤,从⽹络上了解到注解、AOP是⼀种不错的解决⽅案,主要有两种⽅式: 1、通过注解获取结果集转为JSON字符串,通过正则查找附加字段; 2、通过获取结果集中相关字段上注解,此种⽅法有两个需要解决的问题,⽗类继承字段、嵌合对象难以解决获取对应注解字段问题,解决起来均⽐较⿇烦; 因此本⽂采⽤第⼀种⽅法,能有效规避第⼆种⽅法相关问题,做到逻辑相对简单,引⼊缓存提⾼效率。
⼀、新建注解 标注⽅法上使⽤1 @Retention(RetentionPolicy.RUNTIME)2 @Target(ElementType.METHOD)3 @Documented4public @interface TranslationDict {5 FieldParam[] value();6 } 注解参数:FieldParam1 @Retention(RetentionPolicy.RUNTIME)2 @Target({ElementType.FIELD})3 @Documented4public @interface FieldParam {56/**7 * 字段类型默认字典8 * Constant.FIELDTYPE_DICT 为⾃定义常量9 * @return10*/11int type() default Constant.FIELDTYPE_DICT;1213/**14 * 字典dictType15 * @return16*/17 String dictType() default "";1819/**20 * 要翻译的字段⽬标字段为翻译的字段+Str21 * @return22*/23 String targetField() default "";2425/**26 * 要翻译的字段值类型27 * @return28*/29 Class targetFieldValueClazz() default String.class;3031 }⼆、注解的使⽤ 在需要转义⽅法体上添加注解,在注解上指定需要转义的字段,不声明则使⽤默认值。
AOP标注-实例详解

AOP简介AOP(Aspect Orient Programming),也就是面向切面编程,作为面向对象编程的补充。
面向切面编程(AOP)和面向对象编程(OOP)互为补充,面向对象编程将程序分解成各个层次的对象,而面向切面编程将程序运行过程分解成各个切面,可以这样理解,面向对象编程从静态角度考虑程序结构,面向切面编程是从动态角度考虑运行过程。
AOP专门用来处理具有横切性质的系统服务,如事务管理、安全检查、缓存、对象池管理等。
基本概念切面(Aspect):业务流程运行的某个特定步骤,也就是应用运行过程中的关注点,关注点可以横切多个对象,所以常常也称为横切关注点。
连接点(Joinpoint):程序运行过程中明确的点,如方法的调用,或者异常的抛出。
Spring AOP 中,连接点总是方法的调用。
增强处理(Advice):AOP框架在特定在特定的切入点执行的增强处理。
出来有”around”、”before”、”after”等类型。
切入点(Pointcut):可以插入增强处理的连接点。
简而言之,当某个连接点满足指定要求时,该连接点将被添加增强处理,该连接点也就变成了切入点。
引入:将方法或者字段添加到被处理的类中。
Spring允许引入新的接口到任何被处理的对象。
目标对象(Target):被AOP框架进行增强处理的对象,也被称为增强的对象。
如果AOP框架是通过运行时代理来实现的,那么这个对象是一个被代理的对象。
AOP代理:AOP框架创建的对象,简单地说代理就是对目标对象的加强。
Spring中的AOP 代理可以是JDK动态代理,也可以是DBLIB代理。
前者为实现接口的目标对象的代理,后者为不实现接口的目标对象的代理。
织入(Weaving):将增强处理添加到目标对象中,并创建一个被增强的对象(AOP代理)的过程就是织入。
织入有两种方式:编译时增强(AspectJ)和运行时增强(DGLIB)。
AOP代理实际是由AOP框架动态生成的一个对象,该对象包含了目标对象全部的方法。
基于注解的Spring AOP的配置和使用

基于注解的Spring AOP的配置和使用AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程。
可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。
AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可以说也是这种目标的一种实现。
我们现在做的一些非业务,如:日志、事务、安全等都会写在业务代码中(也即是说,这些非业务类横切于业务类),但这些代码往往是重复,复制——粘贴式的代码会给程序的维护带来不便,AOP就实现了把这些业务需求与系统需求分开来做。
这种解决的方式也称代理机制。
先来了解一下AOP的相关概念,《Spring参考手册》中定义了以下几个AOP的重要概念,结合以上代码分析如下:∙切面(Aspect):官方的抽象定义为“一个关注点的模块化,这个关注点可能会横切多个对象”,在本例中,“切面”就是类TestAspect所关注的具体行为,例如,AServiceImpl.barA()的调用就是切面TestAspect所关注的行为之一。
“切面”在ApplicationContext 中<aop:aspect>来配置。
∙连接点(Joinpoint):程序执行过程中的某一行为,例如,UserService.get 的调用或者UserService.delete抛出异常等行为。
∙通知(Advice):“切面”对于某个“连接点”所产生的动作,例如,TestAspect 中对com.spring.service包下所有类的方法进行日志记录的动作就是一个Advice。
其中,一个“切面”可以包含多个“Advice”,例如ServiceAspect。
∙切入点(Pointcut):匹配连接点的断言,在AOP中通知和一个切入点表达式关联。
例如,TestAspect中的所有通知所关注的连接点,都由切入点表达式execution(* com.spring.service.*.*(..))来决定。
(10条消息)springboot自定义注解使用AOP实现请求参数解密以及响应数据加密

(10条消息)springboot⾃定义注解使⽤AOP实现请求参数解密以及响应数据加密⼀、前⾔本篇⽂章将依托与SpringBoot平台,⾃定义注解⽤来标识接⼝请求是否实现加密解密。
使⽤AOP切⾯来具体操作解密加密,实现对源代码的低耦合,不在原基础上做很⼤的改动。
本篇⽂章的所有⽰例,都上传到我的github中,欢迎⼤家拉取测试,欢迎star github实现要求:1. ⾃定义⼀个注解@Secret,⽤来标识需要实现加密解密作⽤在Controller类上,表⽰此Controller类的所有接⼝都实现加密解密作⽤来单⼀⽅法上,表⽰此接⼝⽅法需要实现加密解密2. 使⽤AOP切⾯编程实现在接⼝⽅法执⾏之前将前端的加密参数解密并重新赋给接⼝参数在接⼝⽅法响应之后,将返回的数据进⾏加密返回3. 在配置⽂件中配置,是否开启全局的加密解密操作实现流程:1. 前端请求的接⼝将请求参数json通过AES加密⽣成加密字符串,然后将加密字符串通过名为encyptStr字段传递给后端。
2. AOP前置⽅法拦截,将encyptStr字符串通过AES解密得到原始请求参数json,将json映射为请求⽅法的参数对象User。
3. 接⼝通过参数成功响应,并将响应数据直接返回。
4. AOP后置⽅式拦截,将响应参数data字段⾥的数据AES加密,并返回给前端5. 前端收到请求响应,通过code判断请求是否成功,AES加密data字段得到需要的数据。
⼆、实现操作1. 创建SPRINGBOOT项⽬创建⼀个SpringBoot项⽬,导⼊必要的maven依赖。
使⽤AOP切⾯需要导⼊AOP的启动器lombok是⼀个通过注解简化代码的⼯具,在idea中使⽤需要安装lombok插件json转换⼯具,apache⼯具类pom.xml1. <!-- web依赖 -->2. <dependency>3. <groupId>org.springframework.boot</groupId>4. <artifactId>spring-boot-starter-web</artifactId>5. </dependency>6.7. <!-- AOP切⾯依赖 -->8. <dependency>9. <groupId>org.springframework.boot</groupId>10. <artifactId>spring-boot-starter-aop</artifactId>11. </dependency>12.13. <!-- lombok⼯具 -->14. <dependency>15. <groupId>org.projectlombok</groupId>16. <artifactId>lombok</artifactId>17. <optional>true</optional>18. </dependency>19.20. <!-- json操作类 -->21. <dependency>22. <groupId>com.alibaba</groupId>23. <artifactId>fastjson</artifactId>24. <version>1.2.52.sec06</version>25. </dependency>26. <!-- String⼯具包 -->27. <dependency>28. <groupId>mons</groupId>29. <artifactId>commons-lang3</artifactId>30. <version>3.9</version>31. </dependency>2. ⾃定注解@SECRET我们通过⾃定义的注解,来标识类或接⼝,告诉AOP哪些类或⽅法需要执⾏加密解密操作,更加的灵活。
AOP方法拦截获取参数上的注解

AOP⽅法拦截获取参数上的注解获取参数注解在spring aop中,⽆论是前置通知的参数JoinPoint,还是环绕通知的参数ProceedingJoinPoint,都可以通过以下⽅法获得⼊参: MethodSignature signature= (MethodSignature) jp.getSignature();根据源码分析,MethodSignature封装了两个⽅法,⼀个获取⽅法的返回值类型,⼀个是获取封装的Method对象,getReturnType()可以⽤在环绕通知中,我们可以根据这个class类型,做定制化操作.⽽method的参数和参数上的注解,就可以从getMethod()返回的Method对象中拿,api如下:// 获取⽅法上的注解XXX xxx = signature.getMethod().getAnnotation(XXX.class)//获取所有参数上的注解Annotation[][] parameterAnnotations= signature.getMethod().getParameterAnnotations();只有所有的参数注解怎么获取对应参数的值呢?获取所有参数注解返回的是⼀个⼆维数组Annotation[][],每个参数上可能有多个注解,是⼀个⼀维数组,多个参数⼜是⼀维数组,就组成了⼆维数组,所有我们在遍历的时候,第⼀次遍历拿到的数组下标就是⽅法参数的下标,for (Annotation[] parameterAnnotation: parameterAnnotations) {int paramIndex= ArrayUtils.indexOf(parameterAnnotations, parameterAnnotation);}再根据Object[] args= joinPoint.getArgs();拿到所有的参数,根据指定的下标即可拿到对象的值for (Annotation[] parameterAnnotation: parameterAnnotations) {int paramIndex= ArrayUtils.indexOf(parameterAnnotations, parameterAnnotation);for (Annotation annotation: parameterAnnotation) {if (annotation instanceof XXX){Object paramValue = args[paramIndex]}}}通过以上⽅法,即可找到你想要的参数注解,并拿到对应参数的值啦!。
AOP配置(含注解)详解

AOP配置(含注解)详解AOP(Aspect-Oriented Programming)是面向切面编程的缩写,是一种通过将横切关注点(cross-cutting concern)从业务逻辑代码中分离出来的编程思想和技术。
AOP通过在程序中定义切点(Join point)和通知(Advice),可以在不修改原有代码的情况下,对系统进行横向扩展,实现一些跨越多个对象和模块的功能。
AOP可以通过XML配置或者注解配置来实现,下面将以注解配置为例进行详细解析。
首先,我们需要在项目中引入相关的AOP依赖,如Spring AOP。
然后,我们需要在Spring的配置文件中启用AOP功能,这可以通过在配置文件中添加`<aop:aspectj-autoproxy/>`来实现。
这样,Spring就会自动扫描并自动生成代理类以实现AOP。
接下来,我们需要定义切点和通知。
切点是在程序中定义的一些特定的方法,它们可以被AOP框架所拦截。
通知则是在切点被拦截时执行的一段代码。
除了切面、切点和通知,AOP还涉及到一些其他的概念,如切入点、连接点和增强器。
切入点是一个或多个切点的集合,用于定义一组相关的切点。
连接点是在程序中与切点相匹配的特定位置,如方法的执行点。
增强器则是在通知被调用之前或之后,对连接点进行拦截并执行相应的通知。
总之,AOP通过在程序中定义切点和通知,可以实现对系统中特定方法的拦截和增强。
它可以很好地解耦系统的各个模块,并提供了一种便捷的方式来实现横切关注点的功能。
需要注意的是,AOP是一种非常强大和灵活的编程思想和技术,它可以用于很多方面,如日志记录、性能监控、安全检查等。
在使用AOP时,需要充分考虑系统的复杂性和可维护性,避免过度使用AOP,以免产生不必要的复杂性和难以维护的代码。
同时,需要合理地选择切点和通知,保持代码的简洁和可读性。
SpringAOP切面日志Demo配置文件方式与注解方式

SpringAOP切⾯⽇志Demo配置⽂件⽅式与注解⽅式⼀、配置⽂件⽅式1、配置applicationContext.xml,<bean id="logAopBean"class="mon.aop.LogAop"></bean><aop:config><aop:aspect id="logAspect"ref="logAopBean"><aop:pointcut expression="execution(* com.demo..*(..))" id="allMethod"/><aop:before method="before" pointcut-ref="allMethod" /><aop:after-throwing method="afterThrowing" pointcut-ref="allMethod" /><aop:after-returning method="afterReturn" pointcut-ref="allMethod" /><aop:after method="after" pointcut-ref="allMethod" /></aop:aspect></aop:config>2、⽇志处理类,/*** LogAop.java** Shanghai NTT DATA Synergy Software Co., Ltd. All Rights Reserved.* @author wyl* @date 2016-10-18*/package mon.aop;import ng.JoinPoint;import ng.ProceedingJoinPoint;/*** @author wyl* @Description TODO* @date 2016-10-18**/public class LogAop {public void before(JoinPoint call){String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println("开始执⾏:"+className+"."+methodName+"()⽅法...");}public void afterThrowing(JoinPoint call){String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println(className+"."+methodName+"()⽅法抛出了异常...");}public void afterReturn(JoinPoint call){String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println(className+"."+methodName+"()⽅法正常执⾏结束...");}public void after(JoinPoint call){String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println(className+"."+methodName+"()最终执⾏步骤(finally)...");}/*//⽤来做环绕通知的⽅法可以第⼀个参数定义为ng.ProceedingJoinPoint类型public Object doAround(ProceedingJoinPoint call) throws Throwable {Object result = null;this.before(call);//相当于前置通知try {result = call.proceed();this.afterReturn(call); //相当于后置通知} catch (Throwable e) {this.afterThrowing(call); //相当于异常抛出后通知throw e;}finally{this.after(call); //相当于最终通知}return result;}*/}⼆、注解⽅式1、配置applicationContext.xml,<bean id="logAspectBean"class="mon.aop.LogAnnotationAspect"></bean> <aop:aspectj-autoproxy/>2、⽇志处理类,/*** LogAnnotationAspect.java** Shanghai NTT DATA Synergy Software Co., Ltd. All Rights Reserved.* @author wyl* @date 2016-10-18*/package mon.aop;import ng.JoinPoint;import ng.ProceedingJoinPoint;import ng.annotation.After;import ng.annotation.AfterReturning;import ng.annotation.AfterThrowing;import ng.annotation.Aspect;import ng.annotation.Before;import ng.annotation.Pointcut;/*** @author wyl* @Description TODO* @date 2016-10-18**/@Aspect //定义切⾯类public class LogAnnotationAspect {@SuppressWarnings("unused")//定义切⼊点,提供⼀个⽅法,这个⽅法的名字就是改切⼊点的id@Pointcut("execution(* com.demo..*(..))")private void allMethod(){}//针对指定的切⼊点表达式选择的切⼊点应⽤前置通知@Before("allMethod()")public void before(JoinPoint call) {String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println("开始执⾏:"+className+"."+methodName+"()⽅法...");}//访问命名切⼊点来应⽤后置通知@AfterReturning("allMethod()")public void afterReturn(JoinPoint call) {String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println(className+"."+methodName+"()⽅法正常执⾏结束...");}//应⽤最终通知@After("allMethod()")public void after(JoinPoint call) {String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println(className+"."+methodName+"()最终执⾏步骤(finally)...");}//应⽤异常抛出后通知@AfterThrowing("allMethod()")public void afterThrowing(JoinPoint call) {String className = call.getTarget().getClass().getName();String methodName = call.getSignature().getName();System.out.println(className+"."+methodName+"()⽅法抛出了异常...");}//应⽤周围通知//@Around("allMethod()")public Object doAround(ProceedingJoinPoint call) throws Throwable{Object result = null;this.before(call);//相当于前置通知try {result = call.proceed();this.afterReturn(call); //相当于后置通知} catch (Throwable e) {this.afterThrowing(call); //相当于异常抛出后通知throw e;}finally{this.after(call); //相当于最终通知}return result;}}。
AOP+自定义注解实现全局参数校验

AOP+⾃定义注解实现全局参数校验AOP+⾃定义注解实现全局参数校验在开发过程中,⽤户传递的数据不⼀定合法,虽然可以通过前端进⾏⼀些校验,但是为了确保程序的安全性,保证数据的合法,在后台进⾏数据校验也是⼗分必要的。
后台的参数校验在controller⽅法中校验:后台的参数是通过controller⽅法获取的,所以最简单的参数校验的⽅法,就是在controller⽅法中进⾏参数校验。
在controller⽅法中如果进⾏参数校验会有⼤量重复、没有太⼤意义的代码。
使⽤拦截器、过滤器校验为了保证controller中的代码有更好的可读性,可以将参数校验的⼯作交由拦截器(Interceptor)或者过滤器(Filter)来完成,但是此时⼜存在⼀个问题:⾮共性的参数需要每个⽅法都创建⼀个与之对应的拦截器(或者过滤器)。
实现对Entity的统⼀校验鉴于上述解决⽅案的缺点,我们可以借助AOP的思想来进⾏统⼀的参数校验。
思想是通过⾃定义注解来完成对实体类属性的标注,在AOP中扫描加了⾃定义注解的属性,对其进⾏注解属性标注的校验。
对于不满⾜的参数直接抛出⾃定义异常,交由全局异常处理来处理并返回友好的提⽰信息。
在介绍此⽅法之前,我们先来介绍⼀下使⽤其会⽤到的⼀些内容。
⾃定义异常在开发过程中,经常需要抛出⼀些异常,但是异常中没有状态码,⾃定义描述等属性。
所以可以⾃定义⼀个异常。
抛出异常时,使⽤全局异常处理,通过全局异常来处理此异常。
注意:Aspect中的异常只有RuntimeException(及其⼦类)能被全局异常处理。
所以我们通常将⾃定义异常定义为运⾏时异常。
package mon.exception;import lombok.*;/*** @Author: rayfoo@* @Date: 2020/7/20 9:26 下午* @Description: ⾃定义的异常...*/@Getter@Setter@Builder@NoArgsConstructor@AllArgsConstructorpublic class MyException extends RuntimeException{private int code;private String msg;}断⾔类在代码的执⾏过程中,我们经常需要在特定条件下(⼀般为是否满⾜某条件)抛出异常,此时需要加⼊抛异常、返回状态码、错误信息、记录⽇志等操作,此操作是⼤量重复的操作,所以借助Junit中Assert的思想,创建了下述的断⾔⼯具类,⽤于在指定条件下抛出⼀个⾃定义异常。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
AOP编程中注解参数详解@Pointcut("execution(* transfer(..))")private void anyOldTransfer() {}切入点指定者的支持Spring AOP 支持在切入点表达式中使用如下的AspectJ切入点指定者:1:execution:匹配方法执行的连接点,这是你将会用到的Spring的最主要的切入点指定者。
2:within:限定匹配特定类型的连接点(在使用Spring AOP的时候,在匹配的类型中定义的方法的执行)。
3:this:限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中bean reference (Spring AOP 代理)是指定类型的实例。
4: target:限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中目标对象(被代理的appolication object)是指定类型的实例。
5: args:限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中参数是指定类型的实例。
6: @target:限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中执行的对象的类已经有指定类型的注解。
7: @args:限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中实际传入参数的运行时类型有指定类型的注解。
8: @within:限定匹配特定的连接点,其中连接点所在类型已指定注解(在使用Spring AOP 的时候,所执行的方法所在类型已指定注解)。
9: @annotation:限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中连接点的主题有某种给定的注解合并切入点表达式切入点表达式可以使用‘&&', '||' 和 '!'来合并.还可以通过名字来指向切入点表达式。
切入点表达式的基本语法Spring AOP 用户可能会经常使用 execution pointcut designator。
执行表达式的格式如下:execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)除了返回类型模式(上面代码片断中的ret-type-pattern),名字模式和参数模式以外,所有的部分都是可选的。
返回类型模式决定了方法的返回类型必须依次匹配一个连接点。
类型匹配模式1:*:匹配任何数量字符;比如模式 (*,String) 匹配了一个接受两个参数的方法,第一个可以是任意类型,第二个则必须是String类型2:..:匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数,可以使零到多个。
3: +:匹配指定类型的子类型;仅能作为后缀放在类型模式后边。
类型匹配模式示例1:ng.String 匹配String类型;2:java.*.String 匹配java包下的任何“一级子包”下的String类型;如匹配ng.String,但不匹配ng.ss.String3:java..* 匹配java包及任何子包下的任何类型;如匹配ng.String、ng.annotation.Annotation4:ng.*ing 匹配任何ng包下的以ing结尾的类型;5:ng.Number+ 匹配ng包下的任何Number的子类型;如匹配ng.Integer,也匹配java.math.BigInteger切入点表达式的基本示例,使用execution1:public * *(..)任何公共方法的执行2:* cn.javass..IPointcutService.*()cn.javass包及所有子包下IPointcutService接口中的任何无参方法3:* cn.javass..*.*(..)cn.javass包及所有子包下任何类的任何方法4:* cn.javass..IPointcutService.*(*)cn.javass包及所有子包下IPointcutService接口的任何只有一个参数方法5:* (!cn.javass..IPointcutService+).*(..)非“cn.javass包及所有子包下IPointcutService接口及子类型”的任何方法6:* cn.javass..IPointcutService+.*()cn.javass包及所有子包下IPointcutService接口及子类型的的任何无参方法7:* cn.javass..IPointcut*.test*(java.util.Date)cn.javass包及所有子包下IPointcut前缀类型的的以test开头的只有一个参数类型为java.util.Date的方法,注意该匹配是根据方法签名的参数类型进行匹配的,而不是根据执行时传入的参数类型决定的如定义方法:public void test(Object obj);即使执行时传入java.util.Date,也不会匹配的。
8:* cn.javass..IPointcut*.test*(..) throws IllegalArgumentException, ArrayIndexOutOfBoundsExceptioncn.javass包及所有子包下IPointcut前缀类型的的任何方法,且抛出IllegalArgumentException和ArrayIndexOutOfBoundsException异常9:* (cn.javass..IPointcutService+ && java.io.Serializable+).*(..)任何实现了cn.javass包及所有子包下IPointcutService接口和java.io.Serializable接口的类型的任何方法10:@ng.Deprecated * *(..)任何持有@ng.Deprecated注解的方法11:@ng.Deprecated @cn.javass..Secure * *(..)任何持有@ng.Deprecated和@cn.javass..Secure注解的方法12:@(ng.Deprecated || cn.javass..Secure) * *(..)任何持有@ng.Deprecated或@ cn.javass..Secure注解的方法13:(@cn.javass..Secure *) *(..)任何返回值类型持有@cn.javass..Secure的方法14:* (@cn.javass..Secure *).*(..)任何定义方法的类型持有@cn.javass..Secure的方法15:* *(@cn.javass..Secure (*) , @cn.javass..Secure (*))任何签名带有两个参数的方法,且这个两个参数都被@ Secure标记了,如public void test(@Secure String str1, @Secure String str1);16:* *((@ cn.javass..Secure *))或* *(@ cn.javass..Secure *)任何带有一个参数的方法,且该参数类型持有@ cn.javass..Secure;如public voidtest(Model model);且Model类上持有@Secure注解17:* *(@cn.javass..Secure (@cn.javass..Secure *) ,@ cn.javass..Secure(@cn.javass..Secure *))任何带有两个参数的方法,且这两个参数都被@ cn.javass..Secure标记了;且这两个参数的类型上都持有@ cn.javass..Secure;18:* *(java.util.Map<cn.javass..Model, cn.javass..Model>, ..)任何带有一个java.util.Map参数的方法,且该参数类型是以<cn.javass..Model,cn.javass..Model>为泛型参数;注意只匹配第一个参数为java.util.Map,不包括子类型;如public void test(HashMap<Model, Model> map, String str);将不匹配,必须使用“* *(java.util.HashMap<cn.javass..Model,cn.javass..Model>, ..)”进行匹配;而public void test(Map map, int i);也将不匹配,因为泛型参数不匹配19:* *(java.util.Collection<@cn.javass..Secure *>)任何带有一个参数(类型为java.util.Collection)的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@cn.javass..Secure注解;如public voidtest(Collection<Model> collection);Model类型上持有@cn.javass..Secure切入点表达式的基本示例,使用within匹配指定类型内的方法1:within(cn.javass..*)cn.javass包及子包下的任何方法执行2:within(cn.javass..IPointcutService+)cn.javass包或所有子包下IPointcutService类型及子类型的任何方法3:within(@cn.javass..Secure *)持有cn.javass..Secure注解的任何类型的任何方法必须是在目标对象上声明这个注解,在接口上声明的对它不起作用切入点表达式的基本示例,使用this使用“this(类型全限定名)”匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口方法也可以匹配;注意this中使用的表达式必须是类型全限定名,不支持通配符1:this(cn.javass.spring.chapter6.service.IPointcutService)当前AOP对象实现了 IPointcutService接口的任何方法2:this(cn.javass.spring.chapter6.service.IIntroductionService)当前AOP对象实现了 IIntroductionService接口的任何方法也可能是引入接口切入点表达式的基本示例,使用target使用“target(类型全限定名)”匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;注意target中使用的表达式必须是类型全限定名,不支持通配符1:target(cn.javass.spring.chapter6.service.IPointcutService)当前目标对象(非AOP对象)实现了 IPointcutService接口的任何方法2:target(cn.javass.spring.chapter6.service.IIntroductionService)当前目标对象(非AOP对象)实现了IIntroductionService 接口的任何方法不可能是引入接口切入点表达式的基本示例,使用args使用“args(参数类型列表)”匹配当前执行的方法传入的参数为指定类型的执行方法;注意是匹配传入的参数类型,不是匹配方法签名的参数类型;参数类型列表中的参数必须是类型全限定名,通配符不支持;args属于动态切入点,这种切入点开销非常大,非特殊情况最好不要使用1:args (java.io.Serializable,..)任何一个以接受“传入参数类型为 java.io.Serializable”开头,且其后可跟任意个任意类型的参数的方法执行,args指定的参数类型是在运行时动态匹配的切入点表达式的基本示例,使用@within使用“@within(注解类型)”匹配所以持有指定注解类型内的方法;注解类型也必须是全限定类型名1:@within cn.javass.spring.chapter6.Secure)任何目标对象对应的类型持有Secure注解的类方法;必须是在目标对象上声明这个注解,在接口上声明的对它不起作用切入点表达式的基本示例,使用@target使用“@target(注解类型)”匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;注解类型也必须是全限定类型名1:@target (cn.javass.spring.chapter6.Secure)任何目标对象持有Secure注解的类方法;必须是在目标对象上声明这个注解,在接口上声明的对它不起作用切入点表达式的基本示例,使用@args使用“@args(注解列表)”匹配当前执行的方法传入的参数持有指定注解的执行;注解类型也必须是全限定类型名1:@args (cn.javass.spring.chapter6.Secure)任何一个只接受一个参数的方法,且方法运行时传入的参数持有注解cn.javass.spring.chapter6.Secure;动态切入点,类似于arg指示符;切入点表达式的基本示例,使用@annotation使用“@annotation(注解类型)”匹配当前执行方法持有指定注解的方法;注解类型也必须是全限定类型名1:@annotation(cn.javass.spring.chapter6.Secure )当前执行方法上持有注解 cn.javass.spring.chapter6.Secure将被匹配切入点表达式的基本示例,使用bean使用“bean(Bean id或名字通配符)”匹配特定名称的Bean对象的执行方法;Spring AOP 扩展的,在AspectJ中无相应概念1:bean(*Service)匹配所有以Service命名(id或name)结尾的Bean切入点表达式的基本示例,使用reference pointcut引用其他命名切入点,只有@ApectJ风格支持,Schema风格不支持,如下所示:java代码:查看复制到剪贴板打印@Pointcut(value="bean(*Service)") //命名切入点1private void pointcut1(){}@Pointcut(value="@args(cn.javass.spring.chapter6.Secure)") //命名切入点2 private void pointcut2(){}@Before(value = "pointcut1() && pointcut2()") //引用命名切入点public void referencePointcutTest1(JoinPoint jp) {dump("pointcut1() && pointcut2()", jp);}声明通知通知是跟一个切入点表达式关联起来的,并且在切入点匹配的方法执行之前或者之后或者之前和之后运行。