Spring ProxyFactoryBean 源码分析

从入口开始分析

ProxyFactoryBean继承自FactoryBean,分析其源码首先联想到从getObject入手,代码如下。

    @Override
    public Object getObject() throws BeansException {
        initializeAdvisorChain();
        if (isSingleton()) {
            return getSingletonInstance();
        }
        else {
            if (this.targetName == null) {
                logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
                        "Enable prototype proxies by setting the 'targetName' property.");
            }
            return newPrototypeInstance();
        }
    }

调用initializeAdvisorChain初始化advisor链条,然后根据是否为单例创建代理对象。

AOP执行过程中涉及到的重要节点

  1. initializeAdvisorChain通过读取interceptorNamesBeanFactory工厂内对应的AdviceAdvisorMethodInterceptor通过AdvisorAdapterRegistry.wrap(Advice需要有对应的AdvisorAdapter的支持才可以转换)转换为Advisor然后加载到执行链条中。
  2. AopProxyFactory根据AdvisedSupport(ProxyFactorybean的父类)的配置生成不同的AopProxyJdkDynamicAopProxy或者ObjenesisCglibAopProxy。生成AopProxy时已将AdvisedSupport注入到AopProxy中。
  3. AopProxy 生成代理对象, 当代理对象调用具体方法时,会通过AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice将之前注入到advisorChain中的advisors转换为MethodInterceptorInterceptorAndDynamicMethodMatcher集合。然后根据集合迭代执行Interceptorinvoke,最终反射执行真正对象的方法调用。

AdvisorAdapter的承接作用

DefaultAdvisorAdapterRegistry.java

public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
    private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);
    public DefaultAdvisorAdapterRegistry() {
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }
    @Override
    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
        if (adviceObject instanceof Advisor) {
            return (Advisor) adviceObject;
        }
        if (!(adviceObject instanceof Advice)) {
            throw new UnknownAdviceTypeException(adviceObject);
        }
        Advice advice = (Advice) adviceObject;
        if (advice instanceof MethodInterceptor) {
            // So well-known it doesn't even need an adapter.
            return new DefaultPointcutAdvisor(advice);
        }
        for (AdvisorAdapter adapter : this.adapters) {
            // Check that it is supported.
            if (adapter.supportsAdvice(advice)) {
                return new DefaultPointcutAdvisor(advice);
            }
        }
        throw new UnknownAdviceTypeException(advice);
    }
    @Override
    public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
        List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(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[interceptors.size()]);
    }
    @Override
    public void registerAdvisorAdapter(AdvisorAdapter adapter) {
        this.adapters.add(adapter);
    }
}

AdvisorAdapter.java

public interface AdvisorAdapter {
    boolean supportsAdvice(Advice advice);
    MethodInterceptor getInterceptor(Advisor advisor);
}

前面讲到代理对象执行方法时,无论是注册Advice还是Advisor都是将其转换为MethodInterceptorInterceptorAndDynamicMethodMatcher并调用

Object invoke(MethodInvocation invocation) throws Throwable;

来执行拦截逻辑。所以这中间需要一个AdvisorAdapterAdviceAdvisor来转换为MethodInterceptor。Spring在这里使用了和HandlerMapping一样的设计原则。提供一个supportAdvice方式用于判断是否支持传入进来的Advice,如果支持,那么当传入一个Advisor时,通过获取其Advice,并通过一个MethodInterceptor的子类封装起来返回。
同样的看到AdvisorAdapterRegistry.wrap源码可以发现逻辑为对于Advice类型但非MethodInterceptor类型的adviseObject会循环遍历内部的adapters,一个个判断supportsAdvice,如果支持才会将Advice封装为Advisor返回。后续在拿到Advisor并传入AdvisorAdapter.getInterceptor()时才可以取得到对应的MethodInterceptor。下面贴出MethodBeforeAdviceAdapter的源码来看看。

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, Serializable {
    private MethodBeforeAdvice advice;
    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }
    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
        return mi.proceed();
    }
}

可以看到本质还是调用MethodBeforeAdvice.before来做拦截只不过包装了一下。

JdkDynamicAopProxy如何执行

JdkDynamicAopProxy实现了InvocationHandler接口,所以通过Proxy.newInstance出来的对象方法调用最终会回调JdkDynamicAopProxy.invoke。下面是invoke代码片段

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
    retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
    invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
    retVal = invocation.proceed();
}

getInterceptorsAndDynamicInterceptionAdvice就是上文讲的获取MethodInterceptor和InterceptorAndDynamicMethodMatcher的集合。最终传入ReflectiveMethodInvocation中然后进行proceed。下面我们看看ReflectiveMethodInvocation.proceed内部是如何处理的。

    @Override
    public Object proceed() throws Throwable {
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }
        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                return dm.interceptor.invoke(this);
            }
            else {
                return proceed();
            }
        }
        else {
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

内部记录currentInterceptorIndex索引,如果索引还未超过Interceptors集合的最大索引,代表仍然有interceptor需要调用,此时++currentInterceptorIndex并且获取对应的Interceptor。如果是InterceptorAndDynamicMethodMatcher代表是运行时继续匹配再次执行match,匹配通过后执行拦截逻辑,如果是普通的MethodInterceptor直接调用invoke
在这里由于invoke传入的是ReflectiveMethodInvocation再结合我们在对应的MethodInterceptor.invoke(MethodInvocation invocation)内部调用invocation.proceed,所以这里会形成一个递归调用。所以当所有的Interceptor都调用过后,调用invokeJoinpoint()通过反射调用被代理对象的实际方法。
到此一条完整的AOP执行逻辑已经结束,还有很多细节没有讲,但是没想好如何继续写出来,因为比较零碎,不好组织。有问题欢迎评论探讨

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容