我们发现,我们没有更改过Person类的任何代码,它竟然就有了doOther()方法的功能,这就是引介增强的强大功能。此处使用的Advisor为DefaultIntroductionAdvisor。它也是我们最常用的Advisor:
// 它是一个Advisor,同时也是一个IntroductionInfo public interface IntroductionAdvisor extends Advisor, IntroductionInfo { // 它只有ClassFilter,因为它只能作用在类层面上 ClassFilter getClassFilter(); // 判断这些接口,是否真的能够增强。 DynamicIntroductionAdvice#implementsInterface()方法 void validateInterfaces() throws IllegalArgumentException; } // 它直接事IntroductionAdvisor的实现类。同时也是一个ClassFilter public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFilter, Ordered, Serializable { private final Advice advice; private final Set<Class<?>> interfaces = new LinkedHashSet<>(); private int order = Ordered.LOWEST_PRECEDENCE; // 构造函数们 public DefaultIntroductionAdvisor(Advice advice) { this(advice, (advice instanceof IntroductionInfo ? (IntroductionInfo) advice : null)); } // 如果IntroductionInfo 不等于null,就会把接口都add进去/ // IntroductionInfo 的实现类有常用的:DelegatingIntroductionInterceptor和DelegatePerTargetObjectIntroductionInterceptor public DefaultIntroductionAdvisor(Advice advice, @Nullable IntroductionInfo introductionInfo) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; if (introductionInfo != null) { Class<?>[] introducedInterfaces = introductionInfo.getInterfaces(); if (introducedInterfaces.length == 0) { throw new IllegalArgumentException("IntroductionAdviceSupport implements no interfaces"); } for (Class<?> ifc : introducedInterfaces) { addInterface(ifc); } } } //当然你也可以不使用IntroductionInfo,而自己手动指定了这个接口 public DefaultIntroductionAdvisor(DynamicIntroductionAdvice advice, Class<?> intf) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; addInterface(intf); } ... @Override public void validateInterfaces() throws IllegalArgumentException { for (Class<?> ifc : this.interfaces) { if (this.advice instanceof DynamicIntroductionAdvice && !((DynamicIntroductionAdvice) this.advice).implementsInterface(ifc)) { throw new IllegalArgumentException("DynamicIntroductionAdvice [" + this.advice + "] " + "does not implement interface [" + ifc.getName() + "] specified for introduction"); } } } ... }
DelegatingIntroductionInterceptor和DelegatePerTargetObjectIntroductionInterceptor
这两个类是 Spring AOP 中为 IntroductionInterceptor 介面所提供的实作类别,我们可以直接继承他俩,然后扩展我们自己的行为状态。
public class DelegatingIntroductionInterceptor extends IntroductionInfoSupport implements IntroductionInterceptor { // 需要被代理的那个对象。因为这个类需要子类继承使用,所以一般都是thid @Nullable private Object delegate; /** * Construct a new DelegatingIntroductionInterceptor. * The delegate will be the subclass, which must implement * additional interfaces. * 访问权限事protected,显然就是说子类必须去继承这个类,然后提供空构造函数。代理类就是this */ protected DelegatingIntroductionInterceptor() { init(this); } // 当然,你也可以手动指定delegate public DelegatingIntroductionInterceptor(Object delegate) { init(delegate); } private void init(Object delegate) { Assert.notNull(delegate, "Delegate must not be null"); this.delegate = delegate; implementInterfacesOnObject(delegate); // 移除调这些内部标记的接口们 // We don't want to expose the control interface suppressInterface(IntroductionInterceptor.class); suppressInterface(DynamicIntroductionAdvice.class); } // 如果你要自定义一些行为:比如环绕通知之类的,子类需要复写此方法(否则没有必要了) @Override @Nullable public Object invoke(MethodInvocation mi) throws Throwable { // 判断是否是引介增强 if (isMethodOnIntroducedInterface(mi)) { Object retVal = AopUtils.invokeJoinpointUsingReflection(this.delegate, mi.getMethod(), mi.getArguments()); // 如果返回值就是delegate 本身,那就把本身返回出去 if (retVal == this.delegate && mi instanceof ProxyMethodInvocation) { Object proxy = ((ProxyMethodInvocation) mi).getProxy(); if (mi.getMethod().getReturnType().isInstance(proxy)) { retVal = proxy; } } return retVal; } return doProceed(mi); } ... }
因此,上面的例子Demo,我用DelegatingIntroductionInterceptor改造一下(只需要改造SomeInteIntroductionInterceptor即可):
// 因为我们继承自DelegatingIntroductionInterceptor,所以若我们不做环绕通知个性化,只需要实现接口的方法即可 public class SomeInteIntroductionInterceptor extends DelegatingIntroductionInterceptor implements IOtherInte { @Override public void doOther() { System.out.println("给人贴标签 doOther..."); } }
继承此类,确实少了不少事呢。
DelegatePerTargetObjectIntroductionInterceptor
与DelegatingIntroductionInterceptor不同,DelegatePerTargetObjectIntroductionInterceptor会在内部持有一个目标对象与相应Introduction逻辑实现类之间的映射关系。
当每个目标对象上的新定义的接口方法被调用的时候,它会拦截这些调用。然后以目标对象实例作为键,到它持有的那个映射关系中取得对应当前目标对象实例的Introduction实现类实例。 使用起来和DelegatingIntroductionInterceptor没有太大区别,主要在构造函数上:
1: 可以删除掉SomeInteIntroductionInterceptor类了 2:单独实现引介接口 public class OtherImpl implements IOtherInte { @Override public void doOther() { System.out.println("我是OtherImpl"); } } main方法里修改如下:这样就ok了 Advice advice = new DelegatePerTargetObjectIntroductionInterceptor(OtherImpl.class, IOtherInte.class);
备注:若你需要复写invoke方法的逻辑,请扩展它即可~~~(它的优点是:每次执行目标对象的时候,都可议缓存起来,提高一点效率吧)
总结
Advisor是Spring AOP中非常重要的一个概念,最终代理对象进行执行什么的,都是适配到此处,因此需要重点掌握。
其中,引介增强平时使用得较少,但是在特殊的场景下,它能够解决某一类问题,还是非常不错的~