SpringAOP基本应用
AOP的几个主要概念
- JointPoint:切入点,切面和过程的交点
- PointCut:切入点的集合,如何描述这个集合是本文的主要内容
- Aspect:切面,包含切入的类方法
- Advice:切点的位置描述,包括BeforeAdvice、AfterAdvice等等
- Target:被代理的对象,织入对象
AOP应用示例
使用XML配置
1 | <bean id="aspectbean" class="xx.xx.aspectBean" /> |
使用注解
1 |
|
切入点语法描述
切入点语法可以有下列方式来定义或者通过&& || 和!的方式进行组合:
- execution(…)
- args(…)
- target(…)
- within(…)
- annotation(…)
其中execution是最常见的一种,直接描述执行的方法,几个比较通用的语法有
1 | // 任意的公有方法: |
rgs主要通过方法的参数来描述指定的方法,例如通过下面的表达式指定单个参数且参数在运行时为Serializable的方法进行切入:
1 | args(java.io.Serializable) |
target、within、 annotation这三个都和注解有关。target限制目标对象包含某个注解,within限制所有包含某个注解的类方法,annotation限制包含了某个注解的方法。target和within中传入的注解位于类上,而annotion中传入的注解位于方法上。
个人感觉有些场景用annotion会比较舒服、精确分配,尤其是在需要aop的方法名字没有什么共同点而且方法不是很多的情况下。
获取连接点上下文信息
很多时候进行切入需要相关的上下文信息,比如日志记录时需要在切面方法中知道当前织入的是哪个方法。AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org.aspectj.lang.ProceedingJoinPoint表示连接点对象,该类是JoinPoint的子接口。任何一个增强方法都可以通过将第一个入参声明为JoinPoint访问到连接点上下文的信息。这两个接口的主要方法如下:
JoinPoint
Object[] getArgs()
:获取连接点方法运行时的入参列表;Signature getSignature()
:获取连接点的方法签名对象;Object getTarget()
:获取连接点所在的目标对象;Object getThis()
:获取代理对象本身;
ProceedingJoinPoint
ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法
Object proceed() throws java.lang.Throwable
:通过反射执行目标对象的连接点处的方法;Object proceed(Object[] args) throws java.lang.Throwable
:通过反射执行目标对象连接点处的方法,不过使用新的入参替换原来的入参。
注意事项
spring现在使用aspectj来作为切面的解决方案,那么就需要aspectj相关的jar包,这个jar包一般来说越新越好,且与java版本有关,如果版本比较低,可能会出现”the @annotation pointcut expression is only supported at Java 5 compliance level or above”类似的错误,采用高版本的jar包即可。
在执行时如果因为切入点不是接口方法产生报错,则需要引入CGLib相关的jar包。