关于spring:Introduction-Advice

1、Advice与MethodInterceptor

Advice是被某个切面在特定的连接点采取的操作。Spring 提供了多种Advice,能够不便扩大。Advice的类型包含around(盘绕advice)、before(前置advice) 和 after(后置advice)。在Spring中将Advice建模为一个Interceptor。下图是Spring 中罕用的Advice的继承图。

![](/img/bVc9oW8)

图中的Advice接口时整个Advice体系的根接口,Advice接口的全门路的类名是:org.aopalliance.aop.Advice。这个类是Aop联盟定义的类。

Advice的子类带有Aspectj结尾,这些类是包装Aspectj注解的advice办法。

Spring反对仅反对办法级别的链接点,因而Spring的Advice最终都会通过MethodInterceptor 来执行invoke办法。

Object invoke(@Nonnull MethodInvocation invocation) throws Throwable;

那么可能会有疑难,图中的AspectJMethodBeforeAdvice 没有实现MethodInterceptor,那么是怎么实现Advice操作的呢?Advise和Pointcut一起组成了Advisor,Spring在创立代理对象的时候会查找所有实用对象办法的Advisor,而后通过Advisor创立出MethodInterceptor,具体代码能够参考:AdvisorAdapter及其实现。

明天咱们要介绍的是Introduction Advice。

Introduction Advice(引入告诉)

Spring 看待introduction advice 作为一种非凡的拦挡告诉.
引入(Introduction)须要一个IntroductionAdvisor 和一个实现接口IntroductionInterceptor的类。

public interface IntroductionInterceptor extends MethodInterceptor {

    boolean implementsInterface(Class intf);
}

继承自MethodInterceptor接口的invoke()办法须要实现引入性能。也就是说,如果调用的办法切实一个引入接口办法,引入拦截器负责解决办法调用,而不须要调用连接点的proceed();
Introduction advice 不能和任何pointcut应用,因为它仅实用于类,而不是办法级别。只能用IntroductionAdvisor 来应用introduction advice 。

public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
  ClassFilter getClassFilter();
  void validateInterfaces() throws IllegalArgumentException;
}
public interface IntroductionInfo {
  Class<?>[] getInterfaces();
}

getInterfaces()办法返回被这个Advisor对象引入的接口。
validateInterfaces()办法被外部用来查看引入的接口是否被配置的IntroductionInterceptor来实现。

来看一个Spring test套件的例子,假如咱们想将以下接口引入到一个或者很多个对象中:

public interface Lockable {
  void lock();
  void unlock();
  boolean locked();
}

这个例子解释了一个混入的实现。咱们想要将一个无论任何类型的类转换为Lockable,并能调用lock()和unlock()办法。如果咱们调用lock()办法,咱们想要实现所有的setter办法会抛出LockedException.因而,咱们能够通过一个切面来提供在对一个对象毫不理解的状况下来实现不可变的性能。

首先,咱们须要实现一个IntroductionInterceptor来实现这个艰巨工作。咱们能够通过扩大org.springframework.aop.support.DelegatingIntroductionInterceptor 便当类。当然咱们也能够间接实现IntroductionInterceptor,然而应用DelegatingIntroductionInterceptor在大多数状况下是最好的抉择。

DelegatingIntroductionInterceptor 旨在将介绍委托给所引入接口的实在实现,从而暗藏了拦挡的应用。能够通过结构参数设置任意类型的代理。默认的代理(结构参数没有参数的话)是this对象。因而,在这个例子中,代理对象是实现LockMixin的子类DelegatingIntroductionInterceptor。

public class LockMixin extends DelegatingIntroductionInterceptor implements Lockable {
  private boolean locked;
  public void lock() {
  this.locked = true;
  }
  public void unlock() {
  this.locked = false;
  }
  public boolean locked() {
  return this.locked;
  }
  public Object invoke(MethodInvocation invocation) throws Throwable {
  if (locked() && invocation.getMethod().getName().indexOf("set") == 0) {
  throw new LockedException();
  }
  return super.invoke(invocation);
  }
}

给定一个代理(默认是this对象),DelegatingIntroductionInterceptor 实例查找这个代理实现的所有接口(除了IntroductionInterceptor),并且通过他们反对引入。LockMixin能够通过调用suppressInterface办法来勾销不应该被裸露的接口。

然而,无论一个IntroductionInterceptor筹备反对多少个接口,IntroductionAdvisor都会管制理论裸露哪些接口。 引入的接口暗藏了指标对同一接口的任何实现.

LockMixin扩大了DelegatingIntroductionInterceptor 并且实现了Lockable。父类(DelegatingIntroductionInterceptor) 主动查看到Lockable接口能够被反对引入,咱们不须要特地指定。通常不须要覆写invoke()办法。DelegatingIntroductionInterceptor的实现(如果办法是引入办法,那么调用代理办法,否则持续返回连接点)基本上就满足了。在LockMixIn例子中,,invoke()办法进行了一个set办法检测。

public class LockMixinAdvisor extends DefaultIntroductionAdvisor {
  public LockMixinAdvisor() {
  super(new LockMixin(), Lockable.class);
  }
}

通常引入告诉的Advisor是per-instance(每一个代理对象对应一个Advisor实例),认为引入是有状态的。如何管制per-instance,在Advisor的isPerInstance()中有解释,应用sigleton和prototype范畴的bean定义或者适当的代理创立编程。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理