spring-aop

spring AOP 源码浅析

概述

AbstractAutoProxyCreator通过postProcessAfterInitialization实现AOP功能。

源码部分

  • AbstractAutoProxyCreator

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

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

        // getAdvicesAndAdvisorsForBean 由子类重写
        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;
    }
  • 子类 AbstractAdvisorAutoProxyCreator 中的 getAdvicesAndAdvisorsForBean
    @Override
    @Nullable
    protected Object[] getAdvicesAndAdvisorsForBean(
            Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

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

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        // BeanFacrory 中所有 Advisor 的实现 
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        // 有资格的 Advisor
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

    protected List<Advisor> findCandidateAdvisors() {
        Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
        return this.advisorRetrievalHelper.findAdvisorBeans();
    }

    protected List<Advisor> findAdvisorsThatCanApply(
            List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

        ProxyCreationContext.setCurrentProxiedBeanName(beanName);
        try {
            return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
        }
        finally {
            ProxyCreationContext.setCurrentProxiedBeanName(null);
        }
    }
  • 关于createProxy

    • ProxyFactory 对象中有要代理的bean和这个Bean上的advisor

    • Bean使用哪种代理

      1. 当Bean实现接口时,Spring就会用JDK的动态代理。
      2. 当Bean没有实现接口时,Spring会自动使用CGlib实现,但是前提是项目中导入了CGlib的相关依赖,否则Spring只能使用JDK来代理那些没有实现接口的类,这样生成的代理类会报错。
    • AopProxy有两个实现类JdkDynamicAopProxyCglibAopProxy。都是构造 ReflectiveMethodInvocation.proceed()

      • JdkDynamicAopProxy

            invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            retVal = invocation.proceed();
        
      • CglibAopProxy

            // CglibMethodInvocation 继承于 ReflectiveMethodInvocation
            retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
        
  • ReflectiveMethodInvocation.proceed()

    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 {
                // Dynamic matching failed.
                // Skip this interceptor and invoke the next in the chain.
                return proceed();
            }
        }
        else {
            // MethodInterceptor的实现类在处理完自己的逻辑后,还是会调用procee(),传入this就是为了达到这个目的
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

类图

Advisor

Advisor.png

Advice

Advice.png

Joinpoint

Joinpoint.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • spring-AOP(一) 手动代理 spring的设计原理是构造一个个原子功能,然后不断的通过设计模式在外围进行...
    立志java阅读 859评论 1 1
  • 首先,为了让大家能更有效的理解AOP,先带大家过一下AOP中的术语: 切面(Aspect):指关注点模块化,这个关...
    联旺阅读 401评论 0 0
  • 1、AOP核心概念 1)、横切关注点(对哪些方法进行切入) 对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横...
    steven_it阅读 349评论 0 0
  • Spring AOP 机制源码解读 导读 AOP是Spring框架面向切面的编程思想,AOP采用一种称为“横切”的...
    花神子阅读 426评论 0 3
  • 配置注解版事务 事务管理器 事务管理器的接口是PlatformTransactionManager,其中定义了三个...
    爱撒谎的男孩阅读 1,337评论 0 3