Bootstrap

aop源码解析三-postProcessAfterInitialization

aop源码解析二:postProcessBeforeInstantiation博文中 我们花了很长的一个篇幅介绍一个方法shouldSkip方法 虽然看名字很简单 但里面确实做了很多的事情 虽然最终也是没有去创建代理 但这些工作并不是白做的 解析完以后缓存起来了 后面就可以直接使用了 这次我们看下AnnotationAwareAspectJAutoProxyCreator##postProcessAfterInitialization(Object bean, String beanName)方法

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

在这里看到了我们一直想看到的代理相关的代码 因为创建代理是一件耗时的事情 要做很多的解析 转换等工作 所以根据beanClass``beanName作为缓存的key

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        // 因为寻找切面方法等操作是很浪费时间的操作 所以如果不必操作的话或者已经创建过代理的话 尽量提前返回
        //已经创建过
        if (beanName != null && this.targetSourcedBeans.containsKey(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;
        }

        // 可以看出作者的思路是很清晰的 几句代码概括了要做的事情 然后在方法里面展开
        // advice advisor pointcut 等之间的名次的区别与联系
        // advice : action to take at a joinpoint
        // 1. 寻找适合此bean的切面方法
        // 2. 创建代理
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //创建代理对象 java动态代理或者是基于cglib的代理 cglib代理更高效
            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;
    }

我们又看到了shouldSkip(bean.getClass(), beanName)方法 跟我

;