Spring AOP拾遗

这里不介绍基本的AOP,只记录我在学习过程中自己发现需要注意的点。

需要注意的点

1. 启用AOP

AOP需要显式的启用才能使用,除了在切面编程类上声明@Aspect之外,如果使用Java config的配置方式,需要在配置类上注明@EnableAspectJAutoProxy.如果是xml配置的话,需要使用<aop:config/>
然后Aop的类,也需要通过声明@compent之类的纳入spring管理

2. JoinPoint 和 ProceedingJoinPoint

除了环绕增强,其他类型的增强都是使用JoinPoint的,而环绕增强,需要在切面方法里面显式调用被代理的方法,所以使用ProceedingJoinPoint,调用其中新增的proceed方法。

3. 代理方式

Spring 使用动态代理,可以是JDK自己的动态代理,也可以是字节码增强技术。其中如果使用动态代理方式的话,则能被代理的对象一定要扩展了接口。这在AOP的设置里也会是有的。一般都是用JDK自己的动态代理技术,进而,如果没有接口的话,代理失败。

Spring 的切面,囿于动态代理的方式,只能提供方法级别的切面,实质是通过代理类包装被代理类,拦截对方法的调用。对静态方法、字段是没有办法做切面的。

4. Spring 和AspectJ 有差异

Spring AOP 只提供了AspectJ的一个子集的能力,AspectJ是可以实现对静态方法和字段的切面的。此外,AspectJ还提供了更丰富的API。一些在Spring AOP中模棱两可的概念,在AspectJ中都有不同的用途。
尤其 ApsectJ中除了execution还有call的用法,对target,this的含义有扩展,这里不表
例如

1. 重要!!! target VS this

在Spring AOP中,target代表的是动态代理中,被代理的对象,this代表的是代理对象本身(见这里)[https://stackoverflow.com/a/25962099]。

这会带来一个使用target 和 this,表现不一样的地方:
例如target(com.test.Test)按理说会拦截所有被代理对象是Test的方法,但是,这个切点,也会拦截Object上的toString方法。

原因就是上面提到的,通过target来做切面,被拦截到的是所有被代理的对象是Test的,而不管当前被拦截的对象实际是什么,通过断点调试,我们可以看到,拦截到toString方法的时候,实际被拦截到的方法是Object.toString()。其实这个方法和我们想要的啥关系都没有,只是代理对象继承了Object的toString方法而已。但是由于被代理对象,也就是target还是Test,所以也被拦截了。

而对于this(com.test.Test),上面这种情况拦截到Object的toString方法的情况就不会发生,因为this判断的代理对象的类型,所有继承来的方法(没有被重写),实际切点拦截到的类型不是Tests,而是父类,所以不在拦截的范畴内。

所以看到有些博客写着这么一句话:

使用this做切面,不会拦截到继承的方法,等效于getDeclearMethod得到的方法,去掉其中的私有方法(因为私有方法不会被外部调用,不能代理),使用target会拦截到继承而来的方法,等效于getMethod得到的方法

3. @annotation VS @with

@annotation 只能对方法级别注解做切面,表示对指定注解标记的方法 做节点
@with 只能对类级别注解使用,表示对被指定注解 标记的类下的方法做切点

4. 拦截所有实现某个接口或者类的子类

例如,如果想拦截所有实现了com.test.Test的子类,使用com.test.Test+可以做到,注意这里的加号

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值