关于spring:Spring-AOP-的实现

6次阅读

共计 19685 个字符,预计需要花费 50 分钟才能阅读完成。

在理解 Spring AOP 的实现之前,先理解一些 Spring AOP 的相干概念

AOP 的相干概念

在应用 Spring 进行 AOP 相干的编程时,咱们常常应用 Advice (告诉), PointCut (切点), Advisor (告诉器)来实现咱们须要的性能。

Advice

Advice 是 AOP 联盟定义的一个接口,定义了咱们能够在切点做些什么,即咱们心愿织入的加强逻辑,为切面加强提供织入的入口。在 Spring 中,Advice 作为一个对立的接口,Spring 在 Advice 的根底上定义了具体的告诉类型,比方,

  • BeforeAdvice: 前置加强接口,在指标办法调用之前回调。
  • AfterAdvice : 后置加强接口,在指标办法调用完结并胜利返回时回调。
  • ThrowAdvice : 在抛出异样时回调。
  • Interceptor: 示意一个通用的拦截器,能够在办法的调用前后进行加强。
  • DynamicIntroductionAdvice: 与下面的 Advice 和 Interceptor 不同,DynamicIntroductionAdvice 不对办法进行加强,而是动静的引入新的接口实现。咱们能够为指标类增加一个接口的实现(原来指标类未实现某个接口), 那么通过 DynamicIntroductionAdvice 加强能够为指标类创立实现某接口的代理。

Pointcut

Pointcut 决定 Advice 能够作用于哪些连接点,即通过 Pointcut 咱们能够定义须要加强的办法的汇合。这些办法的汇合能够通过 Pointcut 中定义的规定来选取,当办法合乎 Pointcut 定义的规定时,返回 true。这些规定可是正则表达式,也能够是字符串的匹配等。

Spring 定义了 Pointcut 的接口,Pointcut 接口中定义了用于获取类过滤器和办法匹配器的形象办法。

public interface Pointcut {

    /**
     * Return the ClassFilter for this pointcut.
     * @return the ClassFilter (never {@code null})
     */
    ClassFilter getClassFilter();

    /**
     * Return the MethodMatcher for this pointcut.
     * @return the MethodMatcher (never {@code null})
     */
    MethodMatcher getMethodMatcher();


    /**
     * Canonical Pointcut instance that always matches.
     */
    Pointcut TRUE = TruePointcut.INSTANCE;

}

然而有了类过滤器和办法匹配器,咱们还须要晓得如何应用类过滤器和办法匹配器,因而在实现 Pointcut 的同时也须要实现 MethodMatcher。MethodMatcher 定义了 matches 办法,即用于规定匹配的办法。

public interface MethodMatcher {

    /**
     * Perform static checking whether the given method matches.
     * <p>If this returns {@code false} or if the {@link #isRuntime()}
     * method returns {@code false}, no runtime check (i.e. no
     * {@link #matches(java.lang.reflect.Method, Class, Object[])} call)
     * will be made.
     * @param method the candidate method
     * @param targetClass the target class
     * @return whether or not this method matches statically
     */
    boolean matches(Method method, Class<?> targetClass);

    /**
     * Is this MethodMatcher dynamic, that is, must a final call be made on the
     * {@link #matches(java.lang.reflect.Method, Class, Object[])} method at
     * runtime even if the 2-arg matches method returns {@code true}?
     * <p>Can be invoked when an AOP proxy is created, and need not be invoked
     * again before each method invocation,
     * @return whether or not a runtime match via the 3-arg
     * {@link #matches(java.lang.reflect.Method, Class, Object[])} method
     * is required if static matching passed
     */
    boolean isRuntime();

    /**
     * Check whether there a runtime (dynamic) match for this method,
     * which must have matched statically.
     * <p>This method is invoked only if the 2-arg matches method returns
     * {@code true} for the given method and target class, and if the
     * {@link #isRuntime()} method returns {@code true}. Invoked
     * immediately before potential running of the advice, after any
     * advice earlier in the advice chain has run.
     * @param method the candidate method
     * @param targetClass the target class
     * @param args arguments to the method
     * @return whether there's a runtime match
     * @see MethodMatcher#matches(Method, Class)
     */
    boolean matches(Method method, Class<?> targetClass, Object... args);


    /**
     * Canonical instance that matches all methods.
     */
    MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;

}

下图给出了 Spring 中一些 Pointcut 的继承关系,能够看到具体的实现都集成了 Pointcut 接口和 MethodMatcher 接口。

Advisor

后面介绍了 Advice 的加强逻辑,Pointcut 定义了办法的汇合,然而哪些办法应用什么样的加强逻辑仍旧没有关联起来,Advisor 就是将 Advice 和 Pointcut 联合起来,通过 Advisor,能够定义在某个 Pointcut 连接点上应用哪个 Advice。
Spring 提供了一个 DefaultPointcutAdvisor, 在 DefaultPointcutAdvisor 中有两个属性,别离为 advice 和 pointcut 用来配置 Advice 和 Pointcut。其实现如下所示。

public class DefaultPointcutAdvisor extends AbstractGenericPointcutAdvisor implements Serializable {

    private Pointcut pointcut = Pointcut.TRUE;


    /**
     * Create an empty DefaultPointcutAdvisor.
     * <p>Advice must be set before use using setter methods.
     * Pointcut will normally be set also, but defaults to {@code Pointcut.TRUE}.
     */
    public DefaultPointcutAdvisor() {}

    /**
     * Create a DefaultPointcutAdvisor that matches all methods.
     * <p>{@code Pointcut.TRUE} will be used as Pointcut.
     * @param advice the Advice to use
     */
    public DefaultPointcutAdvisor(Advice advice) {this(Pointcut.TRUE, advice);
    }

    /**
     * Create a DefaultPointcutAdvisor, specifying Pointcut and Advice.
     * @param pointcut the Pointcut targeting the Advice
     * @param advice the Advice to run when Pointcut matches
     */
    public DefaultPointcutAdvisor(Pointcut pointcut, Advice advice) {
        this.pointcut = pointcut;
        setAdvice(advice);
    }


    /**
     * Specify the pointcut targeting the advice.
     * <p>Default is {@code Pointcut.TRUE}.
     * @see #setAdvice
     */
    public void setPointcut(@Nullable Pointcut pointcut) {this.pointcut = (pointcut != null ? pointcut : Pointcut.TRUE);
    }

    @Override
    public Pointcut getPointcut() {return this.pointcut;}


    @Override
    public String toString() {return getClass().getName() + ": pointcut [" + getPointcut() + "]; advice [" + getAdvice() + "]";
    }

}

Spring AOP 的实现

后面曾经介绍了 Spring AOP 的相干概念,然而 Spring AOP 是如何对办法的调用进行拦挡的呢?上面就 Spring AOP 的实现进行剖析。
同样以 Spring 中的单元测试开始 Spring AOP 的实现剖析。
通过以下代码开始 Spring AOP 的实现剖析。

@Test
public void testProxyFactory() {TestBean target = new TestBean();
    ProxyFactory pf = new ProxyFactory(target);
    NopInterceptor nop = new NopInterceptor();
    CountingBeforeAdvice cba = new CountingBeforeAdvice();
    Advisor advisor = new DefaultPointcutAdvisor(cba);
    pf.addAdvice(nop);
    pf.addAdvisor(advisor);
    ITestBean proxied = (ITestBean) pf.getProxy();
    proxied.setAge(5);
    assertThat(cba.getCalls()).isEqualTo(1);
    assertThat(nop.getCount()).isEqualTo(1);
    assertThat(pf.removeAdvisor(advisor)).isTrue();
    assertThat(proxied.getAge()).isEqualTo(5);
    assertThat(cba.getCalls()).isEqualTo(1);
    assertThat(nop.getCount()).isEqualTo(2);
}

上述的代码中创立了一个 TestBean,NopInterceptor, CountingBeforeAdvice 对象,并应用 TestBean 初始化了 ProxyFactory,CountingBeforeAdvice 对象初始化 DefaultPointcutAdvisor,同时将 NopInterceptorDefaultPointcutAdvisor 增加到 ProxyFactory 中。能够看到上述的代码中没有指明 Pointcut, 也就意味着应用了默认的 Pointcut.TRUE, 即对所有的办法都进行加强。

首先来看一下 ProxyFactory 的继承关系。

从上往下看,首先是 TargetClassAware, 定义了一个 getTargetClass()办法用来获取指标对象的 Class,Advised 继承了该接口,Advised 接口定义了获取和设置 AOP 代理工厂 (Aop proxy factory) 配置的办法, 具体代码如下:

public interface Advised extends TargetClassAware {boolean isFrozen();

    boolean isProxyTargetClass();

    Class<?>[] getProxiedInterfaces();

    boolean isInterfaceProxied(Class<?> intf);

    void setTargetSource(TargetSource targetSource);

    TargetSource getTargetSource();

    void setExposeProxy(boolean exposeProxy);

    boolean isExposeProxy();

    void setPreFiltered(boolean preFiltered);

    boolean isPreFiltered();

    Advisor[] getAdvisors();

    default int getAdvisorCount() {return getAdvisors().length;
    }

    void addAdvisor(Advisor advisor) throws AopConfigException;
    
    void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
    
    boolean removeAdvisor(Advisor advisor);
    
    void removeAdvisor(int index) throws AopConfigException;

    int indexOf(Advisor advisor);
    
    boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
    
    void addAdvice(Advice advice) throws AopConfigException;
    
    void addAdvice(int pos, Advice advice) throws AopConfigException;
    
    boolean removeAdvice(Advice advice);
    
    int indexOf(Advice advice);

    String toProxyConfigString();}

而 ProxyConfig 则保留了 AOP 代理工厂的局部属性,能够看成是一个数据基类,如下:

public class ProxyConfig implements Serializable {
    ...
    private boolean proxyTargetClass = false;

    private boolean optimize = false;

    boolean opaque = false;

    boolean exposeProxy = false;

    private boolean frozen = false;
    ...
}

AdvisedSupport 继承了 ProxyConfig 同时实现了 Advised 接口,封装了 AOP 对 Advice 和 Advisor 的相干操作。

/** The AdvisorChainFactory to use. */
AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();

/** Cache with Method as key and advisor chain List as value. */
private transient Map<MethodCacheKey, List<Object>> methodCache;

/**
 * Interfaces to be implemented by the proxy. Held in List to keep the order
 * of registration, to create JDK proxy with specified order of interfaces.
 */
private List<Class<?>> interfaces = new ArrayList<>();

/**
 * List of Advisors. If an Advice is added, it will be wrapped
 * in an Advisor before being added to this List.
 */
private List<Advisor> advisors = new ArrayList<>();

ProxyCreatorSupport 则提供了设置 ProxyFactory 和创立代理对象的办法,创立的具体的代理对象则交给具体的 ProxyFactory 实现。
最上面的则是三个具体的 ProxyFactory 的实现,别离为:

  • ProxyFactory,能够在 IOC 容器中应用申明式配置 AOP。
  • ProxyFactoryBean,须要编程式的应用 AOP
  • AspectProxyFactory,对于应用 AspectJ 的 AOP 利用,集成了 Spring 和 AspectJ。

理解了 ProxyFactory 的继承关系后,持续往下看,咱们曾经晓得了具体的代理的对象的创立交给具体的 ProxyFactory。
咱们次要关注上面用于获取代理对象的这行代码:

ITestBean proxied = (ITestBean) pf.getProxy();

ProxyFactory 的 getProxy 的实现如下:

public Object getProxy() {return createAopProxy().getProxy();}

getProxy()调用 ProxyCreatorSupport 的 createAopProxy()用于创立 AopProxy。

protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();
    }
    return getAopProxyFactory().createAopProxy(this);
}

createAopProxy()先通过 getAopProxyFactory()获取 AopProxyFactory。getAopProxyFactory()间接返回一个 DefaultAopProxyFactory 的对象,而后调用 DefaultAopProxyFactory 的 createAopProxy()办法创立具体的 AopProxy,并传入 this 指针,即 ProxyFactory 对象自身,因为 ProxyFactory 继承了 AdvisedSupport。

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (!NativeDetector.inNativeImage() &&
            (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {Class<?> targetClass = config.getTargetClass();
        if (targetClass == null) {
            throw new AopConfigException("TargetSource cannot determine target class:" +
                    "Either an interface or a target is required for proxy creation.");
        }
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);
        }
        return new ObjenesisCglibAopProxy(config);
    }
    else {return new JdkDynamicAopProxy(config);
    }
}
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {Class<?>[] ifcs = config.getProxiedInterfaces();
    return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
  • config.isOptimize():示意是否应用了优化策略,配置的属性 optimize 值决定;
  • config.isProxyTargetClass():示意是否是代理指标类,配置的属性 proxy-target-class 值决定;
  • hasNoUserSuppliedProxyInterfaces():就是在判断代理的对象是否有实现接口

当代理的是接口时,则应用 JdkDynamicAopProxy,否则应用 ObjenesisCglibAopProxy()。
JdkDynamicAopProxy 保留了 config 和须要代理的接口。

public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {Assert.notNull(config, "AdvisedSupport must not be null");
    if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {throw new AopConfigException("No advisors and no TargetSource specified");
    }
    this.advised = config;
    this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}

当 advised 没有实现 SpringProxy,Advised, DecoratingProxy 接口 AopProxyUtils.completeProxiedInterfaces()会别离增加这三个接口。

到这里 AopProxyFactory 就实例化实现了。持续看 getProxy()做了什么。

public Object getProxy() {return getProxy(ClassUtils.getDefaultClassLoader());
}
public Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating JDK dynamic proxy:" + this.advised.getTargetSource());
    }
    return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}

通过将 classLoader, proxiedInterfaces 和 this 传入到 newProxyInstance 中去创立了指标对象的代理对象。JdkDynamicAopProxy 实现了 InvocationHandler 接口,因而能够将 this 指针传进去创立代理对象。

代理对象创立实现之后,当咱们调用代理对象的办法时,就会回调 JdkDynamicAopProxy 的 invoke()办法。到这里咱们只看见了代理对象的创立,仍旧没有看到怎么对办法进行加强的逻辑,因为对代码进行加强的实现就在 invoke()办法外面。

接下来看一下 invoke()办法。

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object oldProxy = null;
    boolean setProxyContext = false;

    TargetSource targetSource = this.advised.targetSource;
    Object target = null;

    try {if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {// The target does not implement the equals(Object) method itself.
            return equals(args[0]);
        }
        else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {// The target does not implement the hashCode() method itself.
            return hashCode();}
        else if (method.getDeclaringClass() == DecoratingProxy.class) {// There is only getDecoratedClass() declared -> dispatch to proxy config.
            return AopProxyUtils.ultimateTargetClass(this.advised);
        }
        else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            // Service invocations on ProxyConfig with the proxy config...
            return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
        }

        Object retVal;

        if (this.advised.exposeProxy) {
            // Make invocation available if necessary.
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }

        // Get as late as possible to minimize the time we "own" the target,
        // in case it comes from a pool.
        target = targetSource.getTarget();
        Class<?> targetClass = (target != null ? target.getClass() : null);

        // Get the interception chain for this method.
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

        // Check whether we have any advice. If we don't, we can fallback on direct
        // reflective invocation of the target, and avoid creating a MethodInvocation.
        if (chain.isEmpty()) {
            // We can skip creating a MethodInvocation: just invoke the target directly
            // Note that the final invoker must be an InvokerInterceptor so we know it does
            // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        }
        else {
            // We need to create a method invocation...
            MethodInvocation invocation =
                    new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            // Proceed to the joinpoint through the interceptor chain.
            retVal = invocation.proceed();}

        // Massage return value if necessary.
        Class<?> returnType = method.getReturnType();
        if (retVal != null && retVal == target &&
                returnType != Object.class && returnType.isInstance(proxy) &&
                !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
            // Special case: it returned "this" and the return type of the method
            // is type-compatible. Note that we can't help if the target sets
            // a reference to itself in another returned object.
            retVal = proxy;
        }
        else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
            throw new AopInvocationException("Null return value from advice does not match primitive return type for:" + method);
        }
        return retVal;
    }
    finally {if (target != null && !targetSource.isStatic()) {
            // Must have come from TargetSource.
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            // Restore old proxy.
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

invoke()的入参为代理对象,调用的办法,以及调用办法的参数。invoke()方首先查看 method 是不是 equal,hashCode 办法,以及 declaringClass 是不是 DecoratingProxy,是不是须要将 proxy 设置到 AopContext 外面。做完这一系列的查看之后,通过 getInterceptorsAndDynamicInterceptionAdvice()获取 Interceptor 和 Advice 保留到 chain 中,如果 chain 为空,示意没有 interceptor 和 Advice, 则间接通过反射的办法调用指标办法,invokeJoinpointUsingReflection()办法封装反射调用的逻辑。如果非空,则结构一个 ReflectiveMethodInvocation 对象,ReflectiveMethodInvocation 对象的 proceed 办法封装了 Advice 办法的加强逻辑。

先来看一下 getInterceptorsAndDynamicInterceptionAdvice()的实现:

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {MethodCacheKey cacheKey = new MethodCacheKey(method);
    List<Object> cached = this.methodCache.get(cacheKey);
    if (cached == null) {
        cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
        this.methodCache.put(cacheKey, cached);
    }
    return cached;
}

先将 method 封装成 MethodCacheKey,而后尝试从缓存中获取这个 key 对应的缓存,如果没有,则通过 advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice()去获取,这里的 advisorChainFactory 的默认实现是 DefaultAdvisorChainFactory,看一下 getInterceptorsAndDynamicInterceptionAdvice()的实现。

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass) {

    // This is somewhat tricky... We have to process introductions first,
    // but we need to preserve order in the ultimate list.
    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
    Advisor[] advisors = config.getAdvisors();
    List<Object> interceptorList = new ArrayList<>(advisors.length);
    Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
    Boolean hasIntroductions = null;

    for (Advisor advisor : advisors) {if (advisor instanceof PointcutAdvisor) {
            // Add it conditionally.
            PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
            if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                boolean match;
                if (mm instanceof IntroductionAwareMethodMatcher) {if (hasIntroductions == null) {hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
                    }
                    match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
                }
                else {match = mm.matches(method, actualClass);
                }
                if (match) {MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                    if (mm.isRuntime()) {// Creating a new object instance in the getInterceptors() method
                        // isn't a problem as we normally cache created chains.
                        for (MethodInterceptor interceptor : interceptors) {interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                        }
                    }
                    else {interceptorList.addAll(Arrays.asList(interceptors));
                    }
                }
            }
        }
        else if (advisor instanceof IntroductionAdvisor) {IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
            if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {Interceptor[] interceptors = registry.getInterceptors(advisor);
                interceptorList.addAll(Arrays.asList(interceptors));
            }
        }
        else {Interceptor[] interceptors = registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
        }
    }

    return interceptorList;
}

上述的代码首先通过 GlobalAdvisorAdapterRegistry.getInstance()获取了 DefaultAdvisorAdapterRegistry 的实例,DefaultAdvisorAdapterRegistry 注册了三种 Adviced 的适配器,用于将 Advice 适配成 Interceptor。

public DefaultAdvisorAdapterRegistry() {registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
    registerAdvisorAdapter(new AfterReturningAdviceAdapter());
    registerAdvisorAdapter(new ThrowsAdviceAdapter());
}

而后对咱们增加的 Advisor 一一遍历,首先判断是不是 PointcutAdvisor,而后判断是不是 IntroductionAdvisor,如果都不是则认为是 Interceptor。如果以后的 advisor 是 PointcutAdvisor,则先判断是不是提前过滤过了,或者 class 是否合乎 ClassFilter 中定义的规定,如果进一步判断 MethodMatcher 的类型以及 method 是否匹配。无论是 PointcutAdvisor,IntroductionAdvisor 还是 Interceptor,最初都通过 registry.getInterceptors()办法对 advisor 进行适配,将 advisor 对象通过响应的适配器适配成 MethodInterceptor 的一个实例。具体的实现如下所示:

public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {List<MethodInterceptor> interceptors = new ArrayList<>(3);
    Advice advice = advisor.getAdvice();
    if (advice instanceof MethodInterceptor) {interceptors.add((MethodInterceptor) advice);
    }
    for (AdvisorAdapter adapter : this.adapters) {if (adapter.supportsAdvice(advice)) {interceptors.add(adapter.getInterceptor(advisor));
        }
    }
    if (interceptors.isEmpty()) {throw new UnknownAdviceTypeException(advisor.getAdvice());
    }
    return interceptors.toArray(new MethodInterceptor[0]);
}

看一下其中一个 adapter 的实现。

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

    @Override
    public boolean supportsAdvice(Advice advice) {return (advice instanceof MethodBeforeAdvice);
    }

    @Override
    public MethodInterceptor getInterceptor(Advisor advisor) {MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
        return new MethodBeforeAdviceInterceptor(advice);
    }

}

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

    private final MethodBeforeAdvice advice;


    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }


    @Override
    @Nullable
    public Object invoke(MethodInvocation mi) throws Throwable {this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        return mi.proceed();}

}

能够看到对于 BeforeAdvice 最终被是配成了 MethodBeforeAdviceInterceptor,实现了 MethodInterceptor 接口,其中 invoke 办法就是前面拦截器链的入口。

持续看 proceed 的实现。

public Object proceed() throws Throwable {
    // We start with an index of -1 and increment early.
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();
    }

    Object interceptorOrInterceptionAdvice =
            this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
        // Evaluate dynamic method matcher here: static part will already have
        // been evaluated and found to match.
        InterceptorAndDynamicMethodMatcher dm =
                (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
        Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
        if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {return dm.interceptor.invoke(this);
        }
        else {
            // Dynamic matching failed.
            // Skip this interceptor and invoke the next in the chain.
            return proceed();}
    }
    else {
        // It's an interceptor, so we just invoke it: The pointcut will have
        // been evaluated statically before this object was constructed.
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

从索引为 - 1 开始递增,如果所有的 Interceptor 或者 Advice 都调用结束,则通过反射调用指标函数。如果以后的 interceptorOrInterceptionAdvice 是 InterceptorAndDynamicMethodMatcher 的实例,则先通 matches 办法进行匹配,如果匹配胜利,则调用 interceptor 的 invoke 办法,否则跳过,如果不是 InterceptorAndDynamicMethodMatcher 的实例则时示意是一个 interceptor, 也间接调用 invoke 办法。

联合上述的 MethodInterceptor 的 invoke 办法,能够看到所有的 Advice 和 interceptor 串成了一条拦截器链,从头开始,通过 matches 办法进行匹配,匹配胜利则进行加强,否则持续往下查找,直到尾部,调用指标办法,整个过程就是对指标办法的加强过程,也是 AOP 的实现原理。

总结

本文以 ProxyFactory 为例剖析了 Spring AOP 的实现,其实现原理大抵能够分为三个局部:

  1. Advice, Pointcut,Advisor 的实现
  2. 指标对象代理对象的生成。
  3. 对 Advice 进行适配,并组装成一条拦截器链,通过拦截器链对指标办法进行加强。
正文完
 0