Spring源码学习(1) —— ProxyFactoryBean方式实现AOP

实现AOP有很多种方式:

  1. 以编程的方式直接使用JDK或者CGLIB的动态代理来实现;
  2. 以声明/编程的方式使用ProxyFactoryBean来实现;
  3. 以注解的方式使用@AspectJ来实现。

本文主要分析ProxyFactoryBean的方式怎么实现AOP。

1. 类体系结构

ProxyFactoryBean的类体系结构为


Spring源码学习(1) —— ProxyFactoryBean方式实现AOP_第1张图片
ProxyBeanFactory类体系结构

关于该体系结构的简要说明:

  • ProxyConfig是所有产生Spring AOP代理对象的基类,它是一个数据类,主要为其AOP代理对象工厂实现类提供配置属性;
  • AdvisedSupport封装了AOP中对增强和切面的相关操作;
  • ProxyCreatorSupport负责生成具体的AOP代理对象;
  • 除了继承ProxyCreatorSupport,ProxyFactoryBean还实现了三个接口,其中BeanClassLoaderAware用于在jdk创建动态代理时设置类加载器,BeanFactoryAware用于获取当前容器的BeanFactory,而实现FactoryBean则是需要通过它的getObject()方法来获取代理对象。

ProxyConfig中的几个主要属性:

public class ProxyConfig implements Serializable {

    /** use serialVersionUID from Spring 1.2 for interoperability */
    private static final long serialVersionUID = -8409359707199703185L;

    // 标记是否直接对目标类进行代理,而不是通过接口产生代理
    private boolean proxyTargetClass = false;

    // 标记是否对代理进行优化。启动优化通常意味着在代理对象被创建后,增强的修改将不会生效,因此默认值为false。
    // 如果exposeProxy设置为true,即使optimize为true也会被忽略。
    private boolean optimize = false;
    
    // 标记是否需要阻止通过该配置创建的代理对象转换为Advised类型,默认值为false,表示代理对象可以被转换为Advised类型
    boolean opaque = false;

    // 标记代理对象是否应该被aop框架通过AopContext以ThreadLocal的形式暴露出去。
    // 当一个代理对象需要调用它自己的另外一个代理方法时,这个属性将非常有用。默认是是false,以避免不必要的拦截。
    boolean exposeProxy = false;

    // 标记该配置是否需要被冻结,如果被冻结,将不可以修改增强的配置。
    // 当我们不希望调用方修改转换成Advised对象之后的代理对象时,这个配置将非常有用。
    private boolean frozen = false;
...
}

2. 配置文件

一个典型的使用ProxyFactoryBean方式实现AOP的配置文件如下:


    
    
    
    

3. 源码分析

3.1 ProxFactoryBean源码解读

getObject()是获取代理对象的入口方法,在初始化为切面链后,根据目标对象是否为单例来创建对应的代理:

    /**
     * Return a proxy. Invoked when clients obtain beans from this factory bean.
     * Create an instance of the AOP proxy to be returned by this factory.
     * The instance will be cached for a singleton, and create on each call to
     * {@code getObject()} for a proxy.
     * @return a fresh AOP proxy reflecting the current state of this factory
     */
    @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();
        }
    }
3.1.1 初始化切面链

在这里遍历增强列表,根据增强生成切面,加入切面链:

    /**
     * Create the advisor (interceptor) chain. Advisors that are sourced
     * from a BeanFactory will be refreshed each time a new prototype instance
     * is added. Interceptors added programmatically through the factory API
     * are unaffected by such changes.
     */
    private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
        if (this.advisorChainInitialized) {
            return;
        }

        if (!ObjectUtils.isEmpty(this.interceptorNames)) {
            if (this.beanFactory == null) {
                throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
                        "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
            }

            // Globals can't be last unless we specified a targetSource using the property...
            // 全局切面在切面链中不能是最后一个,除非我们指定了目标bean名称或类型
            if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
                    this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
                throw new AopConfigException("Target required after globals");
            }

            // Materialize interceptor chain from bean names.
            for (String name : this.interceptorNames) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Configuring advisor or advice '" + name + "'");
                }

                if (name.endsWith(GLOBAL_SUFFIX)) {
                    if (!(this.beanFactory instanceof ListableBeanFactory)) {
                        throw new AopConfigException(
                                "Can only use global advisors or interceptors with a ListableBeanFactory");
                    }
                    // 添加全局切面
                    addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
                            name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
                }

                else {
                    // If we get here, we need to add a named interceptor.
                    // We must check if it's a singleton or prototype.
                    // 非全局切面,需要判断该增强是否为单例,是则直接从容器中获取实例,否则创建新的实例
                    Object advice;
                    if (this.singleton || this.beanFactory.isSingleton(name)) {
                        // Add the real Advisor/Advice to the chain.
                        advice = this.beanFactory.getBean(name);
                    }
                    else {
                        // It's a prototype Advice or Advisor: replace with a prototype.
                        // Avoid unnecessary creation of prototype bean just for advisor chain initialization.
                        advice = new PrototypePlaceholderAdvisor(name);
                    }
                    // 将增强加入切面链中
                    addAdvisorOnChainCreation(advice, name);
                }
            }
        }

        this.advisorChainInitialized = true;
    }

增加全局切面:

    /**
     * Add all global interceptors and pointcuts.
     */
    private void addGlobalAdvisor(ListableBeanFactory beanFactory, String prefix) {
        // 获取所有切面的bean名称
        String[] globalAdvisorNames =
                BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Advisor.class);
        // 获取所有拦截器的bean名称
        String[] globalInterceptorNames =
                BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, Interceptor.class);
        List beans = new ArrayList(globalAdvisorNames.length + globalInterceptorNames.length);
        Map names = new HashMap(beans.size());
        for (String name : globalAdvisorNames) {
            Object bean = beanFactory.getBean(name);
            beans.add(bean);
            names.put(bean, name);
        }
        for (String name : globalInterceptorNames) {
            Object bean = beanFactory.getBean(name);
            beans.add(bean);
            names.put(bean, name);
        }
        AnnotationAwareOrderComparator.sort(beans);
        for (Object bean : beans) {
            String name = names.get(bean);
            if (name.startsWith(prefix)) {
                // 如果bean名称与全局切面相匹配,加入切面链
                addAdvisorOnChainCreation(bean, name);
            }
        }
    }

这里递归调用,获取当前级联容器中的所有某一类型的bean名称:

    public static String[] beanNamesForTypeIncludingAncestors(ListableBeanFactory lbf, Class type) {
        Assert.notNull(lbf, "ListableBeanFactory must not be null");
        String[] result = lbf.getBeanNamesForType(type);
        if(lbf instanceof HierarchicalBeanFactory) {
            HierarchicalBeanFactory hbf = (HierarchicalBeanFactory)lbf;
            if(hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
                // 遍历父容器的bean
                String[] parentResult = beanNamesForTypeIncludingAncestors((ListableBeanFactory)hbf.getParentBeanFactory(), type);
                List resultList = new ArrayList();
                resultList.addAll(Arrays.asList(result));
                String[] var6 = parentResult;
                int var7 = parentResult.length;

                for(int var8 = 0; var8 < var7; ++var8) {
                    String beanName = var6[var8];
                    // 如果当前容器不包含该bean,加入列表
                    if(!resultList.contains(beanName) && !hbf.containsLocalBean(beanName)) {
                        resultList.add(beanName);
                    }
                }

                result = StringUtils.toStringArray(resultList);
            }
        }

通过增强的实例构造一个切面,加入切面链:

    private void addAdvisorOnChainCreation(Object next, String name) {
        // We need to convert to an Advisor if necessary so that our source reference
        // matches what we find from superclass interceptors.
        Advisor advisor = namedBeanToAdvisor(next);
        if (logger.isTraceEnabled()) {
            logger.trace("Adding advisor with name '" + name + "'");
        }
        addAdvisor(advisor);
    }

调用DefaultAdvisorAdapterRegistry#wrap(),根据传入的增强实例来构造切面:

    private Advisor namedBeanToAdvisor(Object next) {
        try {
            return this.advisorAdapterRegistry.wrap(next);
        }
        catch (UnknownAdviceTypeException ex) {
            // We expected this to be an Advisor or Advice,
            // but it wasn't. This is a configuration error.
            throw new AopConfigException("Unknown advisor type " + next.getClass() +
                    "; Can only include Advisor or Advice type beans in interceptorNames chain except for last entry," +
                    "which may also be target or TargetSource", ex);
        }
    }
    @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.
            // IntroductionInterceptor也继承了MethodInterceptor接口
            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);
    }

默认的切点切面匹配所有类的所有方法:

class TruePointcut implements Pointcut, Serializable {

    public static final TruePointcut INSTANCE = new TruePointcut();

    /**
     * Enforce Singleton pattern.
     */
    private TruePointcut() {
    }

    @Override
    public ClassFilter getClassFilter() {
        return ClassFilter.TRUE;
    }

    @Override
    public MethodMatcher getMethodMatcher() {
        return MethodMatcher.TRUE;
    }
...
}

而this.adapters就是我们的3种增强类型(没有环绕增强和引介增强):

    private final List adapters = new ArrayList(3);


    /**
     * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
     */
    public DefaultAdvisorAdapterRegistry() {
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }

    @Override
    public void registerAdvisorAdapter(AdvisorAdapter adapter) {
        this.adapters.add(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, Serializable {

    private MethodBeforeAdvice advice;


    /**
     * Create a new MethodBeforeAdviceInterceptor for the given advice.
     * @param advice the MethodBeforeAdvice to wrap
     */
    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();
    }

}
3.1.2 产生单例代理对象

构造单例的代理对象有jdk动态代理/cglib两种方式,这里会根据实际条件选择合适的方式:

    /**
     * Return the singleton instance of this class's proxy object,
     * lazily creating it if it hasn't been created already.
     * @return the shared singleton proxy
     */
    private synchronized Object getSingletonInstance() {
        if (this.singletonInstance == null) {
            this.targetSource = freshTargetSource();
            // 如果ProxyFactoryBean设置了自动探测接口属性,并且没有配置代理接口,且不是对类进行代理,则需要获取目标类并设置代理接口(因为默认是通过接口产生代理)
            if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
                // Rely on AOP infrastructure to tell us what interfaces to proxy.
                // 获取目标类
                Class targetClass = getTargetClass();
                if (targetClass == null) {
                    throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
                }
                // 设置代理接口
                setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
            }
            // Initialize the shared singleton instance.
            super.setFrozen(this.freezeProxy);
            // createAopProxy()判断到底是选择jdk还是cglib来生成代理
            this.singletonInstance = getProxy(createAopProxy());
        }
        return this.singletonInstance;
    }

首先刷新目标类:

    /**
     * Return a TargetSource to use when creating a proxy. If the target was not
     * specified at the end of the interceptorNames list, the TargetSource will be
     * this class's TargetSource member. Otherwise, we get the target bean and wrap
     * it in a TargetSource if necessary.
     */
    private TargetSource freshTargetSource() {
        // targetName为空,直接返回targetSource
        if (this.targetName == null) {
            if (logger.isTraceEnabled()) {
                logger.trace("Not refreshing target: Bean name not specified in 'interceptorNames'.");
            }
            return this.targetSource;
        }
        else {
            if (this.beanFactory == null) {
                throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
                        "- cannot resolve target with name '" + this.targetName + "'");
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Refreshing target with name '" + this.targetName + "'");
            }
            // 否则通过targetName获取bean作为目标bean
            Object target = this.beanFactory.getBean(this.targetName);
            return (target instanceof TargetSource ? (TargetSource) target : new SingletonTargetSource(target));
        }
    }

通过这段代码可以看出,配aop配置文件中,优先根据targetName获取目标bean,然后转换成targetSource。
目标类刷新完成后,必要时需要设置代理接口:

    public void setInterfaces(Class... interfaces) {
        Assert.notNull(interfaces, "Interfaces must not be null");
        this.interfaces.clear();
        for (Class ifc : interfaces) {
            addInterface(ifc);
        }
    }

    public void addInterface(Class intf) {
        Assert.notNull(intf, "Interface must not be null");
        if (!intf.isInterface()) {
            throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
        }
        if (!this.interfaces.contains(intf)) {
            this.interfaces.add(intf);
            adviceChanged();
        }
    }
3.1.3 产生原型代理对象

除了在初始化时有区别外,后续原型代理对象和单例代理对象的产生逻辑是一样的,请看代码:

    private synchronized Object newPrototypeInstance() {
        // 在原型模式下,每个代理实都会持有一份独立的配置副本
        if (logger.isTraceEnabled()) {
            logger.trace("Creating copy of prototype ProxyFactoryBean config: " + this);
        }

        ProxyCreatorSupport copy = new ProxyCreatorSupport(getAopProxyFactory());
        // 先刷新切面链,然后拷贝一份给当前代理对象
        TargetSource targetSource = freshTargetSource();
        copy.copyConfigurationFrom(this, targetSource, freshAdvisorChain());
        if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
            // Rely on AOP infrastructure to tell us what interfaces to proxy.
            copy.setInterfaces(
                    ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(), this.proxyClassLoader));
        }
        copy.setFrozen(this.freezeProxy);

        if (logger.isTraceEnabled()) {
            logger.trace("Using ProxyCreatorSupport copy: " + copy);
        }
        return getProxy(copy.createAopProxy());
    }

每次产生新的原型实例时,都需要先刷新切面链:

    /**
     * Return an independent advisor chain.
     * We need to do this every time a new prototype instance is returned,
     * to return distinct instances of prototype Advisors and Advices.
     */
    private List freshAdvisorChain() {
        Advisor[] advisors = getAdvisors();
        List freshAdvisors = new ArrayList(advisors.length);
        for (Advisor advisor : advisors) {
            if (advisor instanceof PrototypePlaceholderAdvisor) {
                PrototypePlaceholderAdvisor pa = (PrototypePlaceholderAdvisor) advisor;
                if (logger.isDebugEnabled()) {
                    logger.debug("Refreshing bean named '" + pa.getBeanName() + "'");
                }
                // Replace the placeholder with a fresh prototype instance resulting
                // from a getBean() lookup
                if (this.beanFactory == null) {
                    throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
                            "- cannot resolve prototype advisor '" + pa.getBeanName() + "'");
                }
                Object bean = this.beanFactory.getBean(pa.getBeanName());
                Advisor refreshedAdvisor = namedBeanToAdvisor(bean);
                freshAdvisors.add(refreshedAdvisor);
            }
            else {
                // Add the shared instance.
                freshAdvisors.add(advisor);
            }
        }
        return freshAdvisors;
    }
3.2 ProxyCreatorSupport源码解读

当第一个AOPProxy代理对象被创建时,active会被设置为true,同时激活AOP代理配置,向容器注册代理回调监听器

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

    private void activate() {
        this.active = true;
        // 这里listeners是啥监听器?默认是空的
        for (AdvisedSupportListener listener : this.listeners) {
            listener.activated(this);
        }
    }
3.3 DefaultAopProxyFactory源码解读

根据实际条件确定到底选择哪种方式来产生代理:

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        // 判断是否启用了优化,是否是对类进行代理,或者目标接口是否是SpringProxy的子接口
        if (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.");
            }
            // 如果目标类是一个接口,或者是Proxy的子接口并且存在于代理类的缓存中,则使用jdk动态代理来生成代理对象
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        // 如果没有启用优化,也不是对类进行代理,并且目标接口不是SpringClass的子接口,则使用jdk动态代理来生成代理对象
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

    /**
     * Determine whether the supplied {@link AdvisedSupport} has only the
     * {@link org.springframework.aop.SpringProxy} interface specified
     * (or no proxy interfaces specified at all).
     */
    // 判断AOP是否只配置了SpringProxy代理接口或者没有配置任何代理接口 
    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
        Class[] ifcs = config.getProxiedInterfaces();
        return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
    }

}
    /**
     * Returns true if and only if the specified class was dynamically
     * generated to be a proxy class using the {@code getProxyClass}
     * method or the {@code newProxyInstance} method.
     *
     * 

The reliability of this method is important for the ability * to use it to make security decisions, so its implementation should * not just test if the class in question extends {@code Proxy}. * * @param cl the class to test * @return {@code true} if the class is a proxy class and * {@code false} otherwise * @throws NullPointerException if {@code cl} is {@code null} */ public static boolean isProxyClass(Class cl) { return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl); }

从这里可以看出,即使启用了优化,或者是配置了对类进行代理,也不一定是使用cglib来产生代理类,只要满足targetClass.isInterface() || Proxy.isProxyClass(targetClass)这个条件,仍然会使用jdk动态代理的方式来产生代理类。

3.4 JdkDynamicAopProxy源码解读

在分析源码之前,我们先了解一下它的类继承体系,如下图所示:


Spring源码学习(1) —— ProxyFactoryBean方式实现AOP_第2张图片
JdkDynamicAopProxy类体系结构

可以发现,JdkDynamicAopProxy继承体系比较简单,只实现了两个接口,分别用来获取产生代理对象的代理对象回调的能力:

  • 实现AopProxy接口,用来获取代理对象
  • 实现InvocationHandler接口,方便代理对象进行回调
    了解了继承体系后,我们再来看一下代码,JdkDynamicAopProxy#getProxy()是获取代理对象的入口方法:
    @Override
    public Object getProxy() {
        return getProxy(ClassUtils.getDefaultClassLoader());
    }

    @Override
    public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
        }
        // 获取配置的代理接口
        Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
        // 判断代理接口中是否实现了equals()方法和hashcode()方法
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        // 使用jdk的动态代理机制返回代理对象
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

    private void findDefinedEqualsAndHashCodeMethods(Class[] proxiedInterfaces) {
        for (Class proxiedInterface : proxiedInterfaces) {
            Method[] methods = proxiedInterface.getDeclaredMethods();
            for (Method method : methods) {
                if (AopUtils.isEqualsMethod(method)) {
                    this.equalsDefined = true;
                }
                if (AopUtils.isHashCodeMethod(method)) {
                    this.hashCodeDefined = true;
                }
                if (this.equalsDefined && this.hashCodeDefined) {
                    return;
                }
            }
        }
    }

invoke()是代理对象的回调方法:

    /**
     * Implementation of {@code InvocationHandler.invoke}.
     * 

Callers will see exactly the exception thrown by the target, * unless a hook method throws an exception. */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; // 获取增强的目标源 TargetSource targetSource = this.advised.targetSource; Class targetClass = null; Object target = null; try { // 如果目标接口没有实现equals()方法,则调用当前equals()方法,hashcode()方法同理 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } // 如果被代理对象本身就实现了Advised接口,不做处理,直接使用反射机制调用 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; // 如果代理通过aop框架暴露出去了,则需要在AopContext中设置ThreadLocal变量 if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be null. Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // 重点,获取所有的拦截器,将初始化时拿到的增强配置通过适配器转化为拦截器 // Get the interception chain for this method. List 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. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } else { // 如果配置了增强,则需要创建回调对象,然后沿着增强链向前推进 // We need to create a method invocation... 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.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); } } }

调用AdvisedSupport,通过切面链工厂类DefaultAdvisorChainFactory,获取所有拦截器,优先从缓存中获取:

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

public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {

    @Override
    public List getInterceptorsAndDynamicInterceptionAdvice(
            Advised config, Method method, Class targetClass) {

        // This is somewhat tricky... We have to process introductions first,
        // but we need to preserve order in the ultimate list.
        // 这里有点棘手,我们需要优先处理引介增强,但又需要保持最终的顺序正确
        List interceptorList = new ArrayList(config.getAdvisors().length);
        Class actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
        // 是否配置了引介增强 
        boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
        // 注册增强的适配器,该适配器用来将增强转换成对应的拦截器
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

        for (Advisor advisor : config.getAdvisors()) {
            // 具有切点的切面
            if (advisor instanceof PointcutAdvisor) {
                // Add it conditionally.
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                // 对类进行静态切点检查
                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                    // 对增强进行适配,转换成对应的拦截器
                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
                        // 是否需要进行动态匹配
                        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;
    }

    /**
     * Determine whether the Advisors contain matching introductions.
     */
    private static boolean hasMatchingIntroductions(Advised config, Class actualClass) {
        for (int i = 0; i < config.getAdvisors().length; i++) {
            Advisor advisor = config.getAdvisors()[i];
            if (advisor instanceof IntroductionAdvisor) {
                IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                if (ia.getClassFilter().matches(actualClass)) {
                    return true;
                }
            }
        }
        return false;
    }

}

从这里对3种类型切面的处理可以看到,一般切面匹配目标类的所有方法,引介切面匹配目标类,而切点切面则需要经过静态检查(类、方法)和动态检查,因此也最为灵活。

以下是注册增强的适配器,该适配器用来将增强转换成对应的拦截器,这里在前面已经分析过:

    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()]);
    }

接下来就是核心方法proceed()了:这里还没完全看完,后续继续更新

    @Override
    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;
            if (dm.methodMatcher.matches(this.method, this.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);
        }
    }

整体流程如下:


Spring源码学习(1) —— ProxyFactoryBean方式实现AOP_第3张图片
image.png

更多技术文章,咱们公众号见,我在公众号里等你~

image.png

你可能感兴趣的:(Spring源码学习(1) —— ProxyFactoryBean方式实现AOP)