Spring Aop: 关于继承和execution target this @annotation
1.多态
target指通过这个对象调用的方法 (匹配标识对象的所有方法) getMethod()
this指调用这个对象的方法 (匹配标识对象实现的方法) getDeclaredMethod()
target/this匹配类及其子类
2.
execution(* com.dao.BaseDao.*(..)) && target(com.dao.impl.UserDaoImpl)
通过UserDaoImpl对象调用<继承><重写><实现>自BaseDao的方法, 会被AOP增强; 如果是通过DeptDaoImpl调用的BaseDao方法就不会被AOP增强.
execution(* com.dao.*.*(..)) && this(com.dao.impl.UserDao)
通过UserDaoImpl对象调用<重写><实现>自BaseDao的方法, 会被AOP增强; 如果UserDaoImpl并没有Override-BaseDao的方法, 那么即使通过UserDaoImpl调用了BaseDao的方法也不会被Aop增强.
如果UserDaoImpl未重写, 但UserDaoImpl的子类UserDaoImplSan重写了, 那么UserDaoImplSan的这个方法会被Aop代理
this语义要强于target
3.关于继承
execution() 匹配父类的某个方法, 那么aop对其子类的这个方法都有效, 即使子类重写了父类的方法扔有效
execution() 匹配子类的某个方法, 如果这个方法是继承自父类的, 那么只有当子类重写了父类的这个方法, aop才对这个方法有效; 否则无效(即使execution不是通过通配符, 而是明确指定子类某个继承方法, 也是无效的)
4.从上面可以看出, target和this主要是用加强某个已存在的pointcut, 如果不考虑复用, 对每个切入点都写详细的execution是可以避免使用target 和 this的
5.@annotation
@annotation表示匹配有这个注解的方法
关键:如何获得注解的值
1.对于直接声明并使用的切入点, 如@Before("@annotation(annoParam)"), 可以在增强方法的参数中直接声明, spring会自动注入
@Before("@annotation(annoParam)") //这里是参数名
public void myAdvice(MyAnno annoParam){}
2.对于通过@Pointcut声明, 或者和execution复合声明的切入点, 如@Before("execution(xxx) && @annotation(MyAnno)), 要通过JoinPoint获得
@Before("myPoint()") public void myAdvice(JoinPoint point){ Signature signature = point.getSignature(); Class clazz = signature.getDeclaringType(); //获得被代理的类 MethodSignature methodSignature = (MethodSignature)signature; Method method = methodSignature.getMethod(); MyAnno myAnno = method.getAnnotation(MyAnno.class); }
//直接使用@annotation(X) X是增强方法的参数名