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 adapters = new ArrayList(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 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[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 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执行逻辑已经结束,还有很多细节没有讲,但是没想好如何继续写出来,因为比较零碎,不好组织。有问题欢迎评论探讨

你可能感兴趣的:(Spring ProxyFactoryBean 源码分析)