Spring AOP

Spring AOP比较常用的使用方式是通过AspectJ表达式声明切入点及处理Advice。
本文介绍继承AbstractAutoProxyCreator的方式来创建代理,区别是这种方式可以对Bean容器初始化的Bean做动态处理,决定是否创建代理、如何创建代理。
AspectJ方式也是创建动态代理,但是相对而言又是一种静态的方式,因为AOP的配置一开始在编译期就已确定了。

结合示例说明

类全名: org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
Spring版本: 4.3.8.RELEASE

创建一个继承AbstractAutoProxyCreator的类

需要实现getAdvicesAndAdvisorsForBean方法以创建代理

import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator;
import org.springframework.beans.BeansException;

public class MyProxyCreator extends AbstractAutoProxyCreator {
    @Override
    protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource customTargetSource) throws BeansException {
        // TODO 
    }
}

getAdvicesAndAdvisorsForBean方法说明

    /**
     * Return whether the given bean is to be proxied, what additional
     * advices (e.g. AOP Alliance interceptors) and advisors to apply.
     * @param beanClass the class of the bean to advise
     * @param beanName the name of the bean
     * @param customTargetSource the TargetSource returned by the
     * {@link #getCustomTargetSource} method: may be ignored.
     * Will be {@code null} if no custom target source is in use.
     * @return an array of additional interceptors for the particular bean;
     * or an empty array if no additional interceptors but just the common ones;
     * or {@code null} if no proxy at all, not even with the common interceptors.
     * See constants DO_NOT_PROXY and PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS.
     * @throws BeansException in case of errors
     * @see #DO_NOT_PROXY
     * @see #PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS
     */
    protected abstract Object[] getAdvicesAndAdvisorsForBean(
            Class<?> beanClass, String beanName, TargetSource customTargetSource) throws BeansException;

这个方法接受容器里产生的Bean的类及名称,以及Bean的原始对象。可以对Spring创建的Bean做代码判断,通过返回值告诉Spring是否要对这个Bean做动态代理。

Object数组返回值

可以返回DO_NOT_PROXY或PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS这两个常量,我们先看一下这两个常量的定义。

    /**
     * Convenience constant for subclasses: Return value for "do not proxy".
     * @see #getAdvicesAndAdvisorsForBean
     */
    protected static final Object[] DO_NOT_PROXY = null;

    /**
     * Convenience constant for subclasses: Return value for
     * "proxy without additional interceptors, just the common ones".
     * @see #getAdvicesAndAdvisorsForBean
     */
    protected static final Object[] PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS = new Object[0];

可以看到DO_NOT_PROXY是null,而PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS是一个空数组。

DO_NOT_PROXY比较好理解,就是对这个Bean不创建代理。

PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS的意思是不创建额外的代理。AbstractAutoProxyCreator有一个字段是interceptorNames,可以对这个字段设值,这里保存的是通用的interceptor的名字,如果返回值是空数组,Spring就会使用默认的代理。

private String[] interceptorNames = new String[0];

如果我们返回对象数据不是空的,那么返回值就作为额外的代理进行创建,也就是说,interceptorNames声明的代理会产生作用,返回值里的声明的代码也同样会产生作用。

创建代理过程

返回的对象数据需要是什么类型才会生效呢,interceptorNames是bean名称,根据bean名称去查找使用对应的切面类。最终在DefaultAdvisorAdapterRegistry的wrap方法里我们可以找到答案。

    @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);
    }

返回的对象数组,如果是MethodInterceptor、Advice会包装成DefaultPointcutAdvisor,最终以Advisor来实现代理。
关于MethodInterceptor、Advice、Advisor、Pointcut等Spring AOP的相关类,不在这里介绍,读者可以在其他地方找到并了解这些基本概念。

完整示例

public class MyProxyCreator extends AbstractAutoProxyCreator {

    @Autowired
    private MyAdvisor myAdvisor;

    @Override
    protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource customTargetSource) throws BeansException {
        if ("singerService".equalsIgnoreCase(beanName)) {
            return new Object[] { myAdvisor };
        } else if (beanClass == SingerService.class) {
            return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
        } else {
            try {
                if (customTargetSource.getTarget() instanceof SingerService) {
                    SingerService singerService = (SingerService) customTargetSource.getTarget();
                    if ("张三".equalsIgnoreCase(singerService.getName())) {
                        return new Object[] { myAdvisor };
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return DO_NOT_PROXY;
    }
}

可以看到,AbstractAutoProxyCreator可以以非常灵活的方式去创建代理