工作生活

Spring源码学习系列(五)之AOP源码解析

2019-07-04  本文已影响0人  just_like_you

今天记录一下Spring#Aop的功能实现过程,以及一些源码解析。

1、首先呢,Aop是从哪里开始的激活的?答案是@EnableAspectJAutoProxy,这是基于注解驱动的,以前基于xml,我们开启注解功能,是用<aop:aspectj-autoproxy/>。那么这两个操作都是怎么开启Spring#Aop功能的呢?直接进入源码,以注解版的为例子:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
   //配置为true强行使用CGLIB动态代理,默认false的时候当类有接口的时候会自动使用Jdk原生的动态代理
    boolean proxyTargetClass() default false;
   //这个属性主要是用来在一些场景下开启动态代理 ex : (在同一service中调用同类方法会让@Transactional注解失效)
    boolean exposeProxy() default false;
}

该注解是一个@Import的派生注解,给容器中加入了一个名为AspectJAutoProxyRegistrar的bean,查看该bean申明,发现其实现了ImportBeanDefinitionRegistrar接口,该接口可以根据像容器中注册一些bean

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * Register, escalate, and configure the AspectJ auto proxy creator based on the value
     * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
     * {@code @Configuration} class.
     */
    @Override
    public void registerBeanDefinitions(
        AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //核心代码
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
}

其中registerAspectJAnnotationAutoProxyCreatorIfNecessary方法,见名知意,如果需要的话注册一个名为AspectJAnnotationAutoProxyCreator的bean,根据猜想继续跟进

    @Nullable
    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            BeanDefinitionRegistry registry, @Nullable Object source) {

        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    }

果然如猜想一样,那么registerOrEscalateApcAsRequired又完成了什么操作呢?

    @Nullable
    private static BeanDefinition registerOrEscalateApcAsRequired(
            Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
            BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                int requiredPriority = findPriorityForClass(cls);
                if (currentPriority < requiredPriority) {
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }
            return null;
        }

        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
        beanDefinition.setSource(source);
        beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
        beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
        return beanDefinition;
    }

主要完成了两个操作:
其中AUTO_PROXY_CREATOR_BEAN_NAME是一个字符串常量org.springframework.aop.config.internalAutoProxyCreator

然后我们要开始分析AnnotationAwareAspectJAutoProxyCreator,使用IDEA查看继承关系:

Aop继承类图
其中红线会发现,这个bean其实是一个BeanPostProcessor的实现类,那么前面后置处理器分析文章我们知道BeanPostProcessor会在Bean的初始化前后执行其后置方法,那么我们进入到继承体系中的AbstractAutoProxyCreator.postProcessAfterInitialization()方法
    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
      //这里的cacheKey其实就是beanName,若beanName不存在,那么则是beanClass
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                          //如果提前的代理引用缓存中没有该bean的存在,那么将执行下面的包装方法
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

其中两个重要的地方,我写了注释,那么我们废话不多少直接进入关键的wrapIfNecessary(bean, beanName, cacheKey)方法

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

其中主要步骤有下列几个:

    private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
    protected boolean isInfrastructureClass(Class<?> beanClass) {
        boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
                Pointcut.class.isAssignableFrom(beanClass) ||
                Advisor.class.isAssignableFrom(beanClass) ||
                AopInfrastructureBean.class.isAssignableFrom(beanClass);
        return retVal;
    }
//这是shouldSkip的核心逻辑
    static boolean isOriginalInstance(String beanName, Class<?> beanClass) {
        if (!StringUtils.hasLength(beanName) || beanName.length() !=
                beanClass.getName().length() + AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX.length()) {
            return false;
        }
        return (beanName.startsWith(beanClass.getName()) &&
                beanName.endsWith(AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX));
    }

1.入口,获取通知方法

    protected Object[] getAdvicesAndAdvisorsForBean(
            Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
        //获取符合条件的Advisor
        List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        //转化成数组
        return advisors.toArray();
    }

2.获取所有符合条件的Advisor

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        //查找所有可用的Advisor
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        //查看所有可以申请的Advisor,使用注解获取方法上面的切入点方法是否一致
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

3.获取所有候选的Advisor,这里会调用子类AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors扩展

    @Override
    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
                //获取所有的Advisor类
        List<Advisor> advisors = super.findCandidateAdvisors();
        // Build Advisors for all AspectJ aspects in the bean factory.
        if (this.aspectJAdvisorsBuilder != null) {
                //构建Advisor,主要就是通过切入点表达式来校验看时候匹配,以及将所有对应的通知方法转化为对应的xxxAdvice类
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }

4.通过AspectMetadata元数据来获取对应通知类的值,调用栈过深,直接到核心方法ReflectiveAspectJAdvisorFactory.getAdvisor

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

        //构造通过Advisor实现类,其中构造方法中有根据不同的通知方法类型,获取不同的Advisor实现类
        return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }

5.调用InstantiationModelAwarePointcutAdvisorImpl.instantiateAdvice中的getAdvice方法构造返回对应通知方法的xxxAdvice类


    public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
                            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

        AbstractAspectJAdvice springAdvice;
              //根据不同通知注解获取不同的通知类
        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;

枚举对应关系:


其中枚举对应关系

最后根据不同注解类型获取的不同通知类:


所有通知类
    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        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.");
            }
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            return new JdkDynamicAopProxy(config);
        }
    }

那么最后创建完了代理对象,当我们执行目标方法的时候自然就是执行代理对象的方法,Spring中使用JdkDynamicAopProxyCglibAopProxy两个类来实现代理方法

JdkDynamicAopProxy为例,当执行目标方法的时候,会执行JdkDynamicAopProxy.invoke()

            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            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.
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                // We need to create a method invocation...
                MethodInvocation invocation =
                        new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // Proceed to the joinpoint through the interceptor chain.
                retVal = invocation.proceed();
            }

这里处理逻辑主要有三个地方

    public Object proceed() throws Throwable {
        //这里是讲传递过来的List<MethodInterceptor>的size -1 和当前索引(默认初始化为-1)进行比较判断,若相等则执行目标方法
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }
              
            // 依次获取下一个拦截器`MethodInterceptor`
        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
          //如果拦截器的类型是InterceptorAndDynamicMethodMatcher,则需要进行切入点表达式匹配
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
            if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
                                //通过则执行拦截器方法
                    return dm.interceptor.invoke(this);
            }
            else {
                     //不执行拦截器方法。
                return proceed();
            }
        }
        else {
                    //直接执行拦截器方法
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

而我们能看到这些MethodInterceptor的类型都是

MethodInterceptor类型
    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        return mi.proceed();
    }
    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        try {
            return mi.proceed();
        }
        finally {
            invokeAdviceMethod(getJoinPointMatch(), null, null);
        }
    }

其实在MethodInvocation.proceed()方法中,我们可以清楚的看到里面的递归调用,其中xxxAdvice执行增强方法与MethodInterceptor.proceed()方法的调用时机,很好的完成了Aop的各种不同位置调用的增强。很多都没有表示清楚,不知道的可以留言。见谅。

上一篇下一篇

猜你喜欢

热点阅读