类继承/接口实现时Spring AOP切入点注意事项
最近好多人问我说我的我的切入点没有错误啊,怎么不起作用?而且大部分情况都是写AOP切入点时带有类继承或接口实现时出现的问题。在此总结一下,方便后人查阅。而且建议使用如IntelliJ IDEA、STS或者Eclipse装AspectJ插件自动显示切入点是否匹配目标对象/目标方法。
1、相关类
1.1、抽象基类
我们在写一些项目时,都会抽象一些基类,比如DAO、Service等。
//基础接口 package com.sishuok.common; public interface BaseService { public void save(); } //基础实现 package com.sishuok.common; public abstract class BaseServiceImpl implements BaseService { @Override public void save() { } }
1.2、实现类
//业务接口 package com.sishuok.user; import com.sishuok.common.BaseService; public interface UserService extends BaseService { public void saveUser();//额外添加的接口 } //业务实现 package com.sishuok.user; import com.sishuok.common.BaseService; import com.sishuok.common.BaseServiceImpl; import org.springframework.stereotype.Service; @Service public class UserServiceImpl extends BaseServiceImpl implements UserService { @Override public void saveUser() {//此处只实现了业务接口,没有覆盖基础实现 } }
2、错误的切入点
2.1、"execution(* com.sishuok.user.UserService.*())" 如果这样写切入点,只能匹配到UserService实现类中的直接实现的方法。即只能匹配saveUser方法,而无法匹配save方法。当然你可以在UserServiceImpl中再覆盖下save方法也可以,但是这样基类就没有意义了。
2.2、”execution(* com.sishuok.user.UserServiceImpl.*())“ 如果想只对UserServiceImpl中的方法进行匹配,这样写也是和上边有一样的问题。
3、正确的切入点
3.1、"execution(* com.sishuok.common.BaseService+.*())" 或者"within(com.sishuok.common.BaseService+)" 或者"this/target(com.sishuok.common.BaseService)" 有朋友会想到,既然这样,反正是对BaseService的所有子类进行匹配,那么就可以按照上边的写法,即匹配BaseService的所有实现类。这样也是可以的。
3.2、"target(com.sishuok.user.UserServiceImpl) && execution(* *())" 这样即可匹配save和saveUser两个方法。
从以上可以总结出:要从基类开始匹配,或者使用target直接匹配具体类。
对于没有接口的,直接类继承实现的,可以参考https://github.com/zhangkaitao/es/tree/master/web/src/main/java/com/sishuok/es/extra/aop。
相关Spring AOP问题:
- »Spring 之AOP AspectJ切入点语法详解
- 请不要再使用低级别的AOP API
- 注入FactoryBean失败分析+解决方案
- spring的二次代理原因及如何排查
- struts2+spring集成bug——使用AOP时可能遇到的问题分析
- 关于spring的aop拦截的问题 protected方法代理问题
- Spring事务不起作用 问题汇总
- Shiro+Struts2+Spring3 加上@RequiresPermissions 后@Autowired失效
- 如何为spring代理类设置属性值
- 在spring中获取代理对象代理的目标对象工具类
- Spring事务处理时自我调用的解决方案及一些实现方式的风险