Spring AOP的深入理解(二)

这篇文章,我来了解一下是如何创建增强AOP代理的.我们已经知道做AOP代理的工作是AnnotationAwareAspectJAutoProxyCreator来做的,所以我们来理解一下这个类.
这个类实现了BeanPostProcessor,然后实现了其中的postProcessAfterInitialization的方法,这个方法的就是AOP操作的开始.而这个方法具体的实现是在它的父类中,我们找到这个方法

@Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

其中wrapIfNecessary就是进行代理的方法,我们继续进入

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // Create proxy if we have advice.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

最开始判断不需要创建代理的情况,并直接返回bean.
其中创建代理的代码为:

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

以上代码就是两个步骤:

  • 获取增强方法或者是增强器
  • 根据获取的增强来创建代理
    我们先来看看是如何获取增强方法的
protected Object[] getAdvicesAndAdvisorsForBean(
            Class beanClass, String beanName, @Nullable TargetSource targetSource) {

        List advisors = findEligibleAdvisors(beanClass, beanName);
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        return advisors.toArray();
    }

protected List findEligibleAdvisors(Class beanClass, String beanName) {
        List candidateAdvisors = findCandidateAdvisors();
        List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

我们看下第二个方法中的两个核心方法findCandidateAdvisors和findAdvisorsThatCanApply.两个方法分别实现了获取增强和应用的先后功能.

获取增强器

findCandidateAdvisors是AnnotationAwareAspectJAutoProxyCreator实现的,因为是通过注解的方式,我们进入到这个方法中

@Override
    protected List findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
        List advisors = super.findCandidateAdvisors();
        // Build Advisors for all AspectJ aspects in the bean factory.
        if (this.aspectJAdvisorsBuilder != null) {
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }

分别实现了在配置文件中获取增强以及通过注解来获取增强.其中通过注解来获取增强的方法是this.aspectJAdvisorsBuilder.buildAspectJAdvisors()来实现的.我们进入到这个方法中去,我们只截取其中核心的代码

String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                            this.beanFactory, Object.class, true, false);
.....
for (String beanName : beanNames) {
.....
Class beanType = this.beanFactory.getType(beanName);
                        if (beanType == null) {
                            continue;
                        }
if (this.advisorFactory.isAspect(beanType)) {
......
List classAdvisors = this.advisorFactory.getAdvisors(factory);
......
}
for (String aspectName : aspectNames) {
            List cachedAdvisors = this.advisorsCache.get(aspectName);
            if (cachedAdvisors != null) {
                advisors.addAll(cachedAdvisors);
            }
            else {
                MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
                advisors.addAll(this.advisorFactory.getAdvisors(factory));
            }
        }

}

大概步骤就是:
从容器中获取所有的bean,然后在其中寻找有注解标记的,对标记有@AspectJ注解的类进行增强器的提取,放入到缓存中.

List classAdvisors = this.advisorFactory.getAdvisors(factory);

这句话就是增强器的提取,我们进入到这个代码中去:
我们看一下核心的代码:

Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);

这个是对普通增强器的提取

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
            int declarationOrderInAspect, String aspectName) {

        validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

        AspectJExpressionPointcut expressionPointcut = getPointcut(
                candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
        if (expressionPointcut == null) {
            return null;
        }

        return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }

getPointCut就是获取切点的信息,也就是对切点表达式的获取,比如说@Before("test()"),最后在进行注解的封装.现在已经获取到了切点的信息,然后就是根据切点的信息,生成增强.也就是这个方法InstantiationModelAwarePointcutAdvisorImpl.

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
            Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

        this.declaredPointcut = declaredPointcut;
        this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
        this.methodName = aspectJAdviceMethod.getName();
        this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
        this.aspectJAdviceMethod = aspectJAdviceMethod;
        this.aspectJAdvisorFactory = aspectJAdvisorFactory;
        this.aspectInstanceFactory = aspectInstanceFactory;
        this.declarationOrder = declarationOrder;
        this.aspectName = aspectName;

        if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
            // Static part of the pointcut is a lazy type.
            Pointcut preInstantiationPointcut = Pointcuts.union(
                    aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

            // Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
            // If it's not a dynamic pointcut, it may be optimized out
            // by the Spring AOP infrastructure after the first evaluation.
            this.pointcut = new PerTargetInstantiationModelPointcut(
                    this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
            this.lazy = true;
        }
        else {
            // A singleton aspect.
            this.pointcut = this.declaredPointcut;
            this.lazy = false;
            this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
        }
    }

最开始就是单纯的赋值.不同的注解就是不同的增强逻辑,其中逻辑的实现就是在instantiateAdvice中完成的,其中就会根据不同的注解生成不同的增强器

switch (aspectJAnnotation.getAnnotationType()) {
            case AtPointcut:
                if (logger.isDebugEnabled()) {
                    logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
                }
                return null;
            case AtAround:
                springAdvice = new AspectJAroundAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtBefore:
                springAdvice = new AspectJMethodBeforeAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtAfter:
                springAdvice = new AspectJAfterAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtAfterReturning:
                springAdvice = new AspectJAfterReturningAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                    springAdvice.setReturningName(afterReturningAnnotation.returning());
                }
                break;
            case AtAfterThrowing:
                springAdvice = new AspectJAfterThrowingAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
                    springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
                }
                break;
            default:
                throw new UnsupportedOperationException(
                        "Unsupported advice type on method: " + candidateAdviceMethod);
        }

通过AtBefore就生成了AspectJMethodBeforeAdvice的增强器,它是怎么使用的呢,这个时候我么要引入一个拦截器的类,如下面的代码:

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

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

}

其中this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());调用的就是我们上面通过注解生成的AspectJMethodBeforeAdvice增强器,使用的就是其中

public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }
//然后一直找
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);

调用的就是最后的invoke方法
以上就是获取增强器的过程,完成了所有增强器的解析,然后就是挑选出适合的增强器

寻找匹配的增强

这个比较简单,就是通过匹配class,来找出适合的增强器

创建代理

Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

......
protected Object createProxy(Class beanClass, @Nullable String beanName,
            @Nullable Object[] specificInterceptors, TargetSource targetSource) {
         ........
        return proxyFactory.getProxy(getProxyClassLoader());
    }

这个方法实际上就是先配置一下proxyFactory然后委托给proxyFactory创建代理.首先就是将增强器,放置到代理工厂去,完成了对增强的封装.然后就是代理的创建和获取了.
接下来就是创建代理了,两种方式jdk动态代理和cglib代理,那么spring是如何选择代理方式的呢?

if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {

这三个方面影响这spring的判断:
isOptimize:这个判断只对cglib代理有效,判断cglib代理是否使用激进的优化策略.
proxyTargetClass:这个为true时,目标类本身被代理,而不是目标类的接口,设置为true的话就是cglib的方式创建
hasNoUserSuppliedProxyInterfaces:是否存在代理接口.
然后就是对cglib代理和jdk动态代理的总结:

  • 如果对象实现了接口,那么默认采用JDK的动态代理实现AOP
  • 如果对象实现了接口,那么强制使用cglib代理实现AOP
  • 如果没有实现接口,必须要采用cglib代理


    Spring AOP的深入理解(二)_第1张图片
    图片.png

    在简单的JDK动态代理中,实现代理的核心就是InvocationHandler,在这个InvacationHandler中重写,三个函数

  • 构造函数,将目标对象传入
  • invoke方法,这个方法中实现了AOP增强的全部逻辑
  • getProxy方法

我们发现JdkDynamicAopProxy实现了InvocationHandler,接口,自然也就有了invoke方法和getProxy方法,我们来看一下invoke方法,这里就是创建的代理的过程
invoke方法中

invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // Proceed to the joinpoint through the interceptor chain.
                retVal = invocation.proceed();

JdkDynamicAopProxy的invoke方法就是创建一个拦截器的链,然后对链进行封装,然后在proceed方法中依次调用.

你可能感兴趣的:(Spring AOP的深入理解(二))