Spring refresh函数(4)——Spring Boot AOP源码实现

refresh()中的finishBeanFactoryInitialization()函数,Spring Boot利用反射机制实例化新的Bean。新Bean创建后,Spring Boot还会继续对Bean进行操作,如填充变量和初始化等。在初始化过程中如果需要对Bean进行切面处理,那么将会利用JDK动态代理或CGLiB动态代理生成Bean的代理对象。

JDK动态代理和CGLIB动态代理

在Spring Boot中根据被代理对象类是否是接口的实现,如果是一个接口的实现类使用JDK动态代理生成代理对象,如果类没有实现接口就用CGLiB动态代理生成代理对象。

JDK动态代理

核心是InvocationHandler接口和Proxy类,目标类必须是一个接口的实现,采用动态代理机制为其生成代理对象实例。

CGLiB动态代理

如果目标类没有实现任何接口,使用开源的动态字节码生成类库CGLIB(Code Generation Library)为目标对象生成代理对象实例。

AnnotationAwareAspectJAutoProxyCreator对象创建

Spring Boot引入包spring-boot-starter-aop默认自动开启装配。


图片选自我的公众号

在registerBeanPostProcessors()函数中先创建AnnotationAwareAspectJAutoProxyCreator对象,在finishBeanFactoryInitialization()函数中通过AnnotationAwareAspectJAutoProxyCreator对象完成代理对象生成逻辑。

registerBeanPostProcessors()函数中调用类PostProcessorRegistrationDelegate中static方法registerBeanPostProcessors()。

下面代码片段中beanFactory.getBean()会实例化AnnotationAwareAspectJAutoProxyCreator对象,注册到BeanFactory中。

Spring中的BeanFactoryPostProcessor是在BeanFactory创建之后,Bean创建之前执行;而BeanPostProcessor在Bean创建之后执行,是对Bean的后续操作。因此BeanPostProcessor的执行顺序是在BeanFactoryPostProcessor之后。先有了Bean,然后执行BeanPostProcessor处理Bean。

类AnnotationAwareAspectJAutoProxyCreator实现了接口BeanPostProcessor。

public static void registerBeanPostProcessors(
      ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    //...略去部分代码...
    // Next, register the BeanPostProcessors that implement Ordered.
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : orderedPostProcessorNames) {
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      orderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
        internalPostProcessors.add(pp);
      }
    }
    //...略去部分代码...
}
图片选自我的公众号

填充对象和生成代理对象

从finishBeanFactoryInitialization()函数进入,依次进入Bean实例化逻辑,执行过程顺序在简书或公众号文章《Spring refresh函数(3)——Spring Boot finishBeanFactoryInitialization》(以后简称“refresh函数(3)”)中讲述。

到类AbstractAutowireCapableBeanFactory中的doCreateBean()方法。“refresh函数(3)”中我们描述方法createBeanInstance()最终利用Java反射机制创建Bean的过程,将方法createBeanInstance()后面的逻辑暂时忽略掉。现在我们继续看之前被忽略的代码逻辑。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
      throws BeanCreationException {
    //这里实例化Bean
    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
      instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    mbd.resolvedTargetType = beanType;

    //...略去部分代码...

    //对实例化的Bean进行填充和初始化
    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
      populateBean(beanName, mbd, instanceWrapper);
      if (exposedObject != null) {
        exposedObject = initializeBean(beanName, exposedObject, mbd);
      }
    }
    catch (Throwable ex) {
      if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
        throw (BeanCreationException) ex;
      }
      else {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
      }
    }
    //...略去部分代码...

    return exposedObject;
}

populateBean()填充Bean

注册的多个BeanPostProcessor依次顺序执行postProcessPropertyValues()方法对Bean进行填充,例如AutowiredAnnotationBeanPostProcessor对象对@Autowired注解描述的Field进行填充。

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    //...略去部分代码...

    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

    if (hasInstAwareBpps || needsDepCheck) {
      PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      if (hasInstAwareBpps) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
          if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            //注册的多个BeanPostProcessor依次对Bean进行填充
            pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvs == null) {
              return;
            }
          }
        }
      }
      if (needsDepCheck) {
        checkDependencies(beanName, mbd, filteredPds, pvs);
      }
    }

    applyPropertyValues(beanName, mbd, bw, pvs);
}
图片选自我的公众号

以AutowiredAnnotationBeanPostProcessor对象为例进入到postProcessPropertyValues()方法中。


@Override
public PropertyValues postProcessPropertyValues(
      PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
      metadata.inject(bean, beanName, pvs);
    }
    catch (BeanCreationException ex) {
      throw ex;
    }
    catch (Throwable ex) {
      throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
}

直接看代码metadata.inject(bean, beanName, pvs)。类InjectionMetadata中inject()方法。


public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable {
    Collection<InjectedElement> elementsToIterate =
        (this.checkedElements != null ? this.checkedElements : this.injectedElements);
    if (!elementsToIterate.isEmpty()) {
      boolean debug = logger.isDebugEnabled();
      for (InjectedElement element : elementsToIterate) {
        if (debug) {
          logger.debug("Processing injected element of bean '" + beanName + "': " + element);
        }
        element.inject(target, beanName, pvs);
      }
    }
}

继续element.inject(target, beanName, pvs)。类InjectionMetadata中的内部类InjectedElement的子类AutowiredFieldElement的inject()方法。BeanFactory的resolveDependency()尝试去处理依赖,如果field是一个Bean,需要对依赖的Bean进行提前的创建和初始化。Java反射机制对Bean进行填充。这里可能涉及到的单例Bean的循环依赖问题,在简书或公众号其他文章中会详细介绍。

@Override
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
      Field field = (Field) this.member;
      Object value;
      if (this.cached) {
        value = resolvedCachedArgument(beanName, this.cachedFieldValue);
      }
      else {
        DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
        desc.setContainingClass(bean.getClass());
        Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
        TypeConverter typeConverter = beanFactory.getTypeConverter();
        try {
          //尝试去处理依赖
          value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
        }
        catch (BeansException ex) {
          throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
        }
        synchronized (this) {
          if (!this.cached) {
            if (value != null || this.required) {
              this.cachedFieldValue = desc;
              registerDependentBeans(beanName, autowiredBeanNames);
              if (autowiredBeanNames.size() == 1) {
                String autowiredBeanName = autowiredBeanNames.iterator().next();
                if (beanFactory.containsBean(autowiredBeanName)) {
                  if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                    this.cachedFieldValue = new ShortcutDependencyDescriptor(
                        desc, autowiredBeanName, field.getType());
                  }
                }
              }
            }
            else {
              this.cachedFieldValue = null;
            }
            this.cached = true;
          }
        }
      }
      //填充field
      if (value != null) {
        ReflectionUtils.makeAccessible(field);
        field.set(bean, value);
      }
    }
}

initializeBean()方法中的AOP

initializeBean()方法英文注释翻译为“初始化给定的Bean实例,应用工厂的回调方法、初始方法和BeanPostProcessor”。在中文理解初始化是一个Bean完整的生产过程或者是对一些属性进行默认设置,而实际上initializeBean()方法在这里是对已经实例化并且填充了field的Bean进行收尾工作,我们讨论的AOP切片就在这里完成的。

/**
 * Initialize the given bean instance, applying factory callbacks
 * as well as init methods and bean post processors.
*/
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
      AccessController.doPrivileged(new PrivilegedAction<Object>() {
        @Override
        public Object run() {
          invokeAwareMethods(beanName, bean);
          return null;
        }
      }, getAccessControlContext());
    }
    else {
      invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
      invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
      throw new BeanCreationException(
          (mbd != null ? mbd.getResourceDescription() : null),
          beanName, "Invocation of init method failed", ex);
    }

    if (mbd == null || !mbd.isSynthetic()) {
      //AOP在这里发生
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

进入类AbstractAutowireCapableBeanFactory中的applyBeanPostProcessorsAfterInitialization()方法。

依次遍历所有的BeanPostProcessor对Bean进行后初始化操作。为专注讨论AOP,这里忽略掉其他无关的BeanPostProcessor,直接看对象AnnotationAwareAspectJAutoProxyCreator(在上文介绍过,在registerBeanPostProcessors()方法中实例化的)。

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
      result = beanProcessor.postProcessAfterInitialization(result, beanName);
      if (result == null) {
        return result;
      }
    }
    return result;
}
图片选自我的公众号

AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator中具体实现postProcessAfterInitialization()方法。

postProcessAfterInitialization()方法中,如果代理对象已经存在于第二级缓存中(this.earlyProxyReferences.contains(cacheKey)代码逻辑,Spring在创建Bean时使用了三级缓存结构),证明已经生成过代理对象,则不再重新生成。

@Override
public Object postProcessAfterInitialization(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;
}

AbstractAutoProxyCreator wrapIfNecessary()方法。getAdvicesAndAdvisorsForBean()方法确定Bean是否需要被代理,如果需要的话,返回创建的切面接口PointcutAdvisor对象。createProxy()方法进行代理的创建。

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (beanName != null && 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;
}
图片选自我的公众号

类InstantiationModelAwarePointcutAdvisorImpl是接口PointcutAdvisor的具体实现类。InstantiationModelAwarePointcutAdvisorImpl对象是被代理Bean的切面的描述。

接下来继续进入类AbstractAutoProxyCreator中createProxy()方法。创建ProxyFactory对象,getProxy()生成代理。

protected Object createProxy(
      Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
      AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    if (!proxyFactory.isProxyTargetClass()) {
      if (shouldProxyTargetClass(beanClass, beanName)) {
        proxyFactory.setProxyTargetClass(true);
      }
      else {
        evaluateProxyInterfaces(beanClass, proxyFactory);
      }
    }

    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    for (Advisor advisor : advisors) {
      proxyFactory.addAdvisor(advisor);
    }

    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
      proxyFactory.setPreFiltered(true);
    }

    return proxyFactory.getProxy(getProxyClassLoader());
}

类ProxyFactory中getProxy()。

public Object getProxy(ClassLoader classLoader) {
    return createAopProxy().getProxy(classLoader);
}

先进入createAopProxy()方法,依次调用类ProxyCreatorSupport中的createAopProxy()方法和类DefaultAopProxyFactory的createAopProxy()方法。

//类ProxyCreatorSupport
protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
      activate();
    }
    return getAopProxyFactory().createAopProxy(this);
}

类DefaultAopProxyFactory的createAopProxy()方法会根据将被代理的类是否是接口的实现,确定使用JDK动态代理还是CGLIB动态代理。如果实现了具体的接口,使用JDK动态代理,否则使用CGLIB动态代理。

所以,Spring AOP利用的是动态代理机制,即使用JDK动态代理,也使用CGLIB动态代理。


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

回到类ProxyFactory中getProxy()。假设我们的类没有实现接口,进入到类CglibAopProxy中getProxy()方法,接下来的操作就是利用CGLIB生成代理对象。

@Override
public Object getProxy(ClassLoader classLoader) {
    if (logger.isDebugEnabled()) {
      logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
    }

    try {
      Class<?> rootClass = this.advised.getTargetClass();
      Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

      Class<?> proxySuperClass = rootClass;
      if (ClassUtils.isCglibProxyClass(rootClass)) {
        proxySuperClass = rootClass.getSuperclass();
        Class<?>[] additionalInterfaces = rootClass.getInterfaces();
        for (Class<?> additionalInterface : additionalInterfaces){
          this.advised.addInterface(additionalInterface);
        }
      }

      // Validate the class, writing log messages as necessary.
      validateClassIfNecessary(proxySuperClass, classLoader);

      // Configure CGLIB Enhancer...
      Enhancer enhancer = createEnhancer();
      if (classLoader != null) {
        enhancer.setClassLoader(classLoader);
        if (classLoader instanceof SmartClassLoader &&
            ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
          enhancer.setUseCache(false);
        }
      }
      enhancer.setSuperclass(proxySuperClass);
      enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
      enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
      enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

      Callback[] callbacks = getCallbacks(rootClass);
      Class<?>[] types = new Class<?>[callbacks.length];
      for (int x = 0; x < types.length; x++) {
        types[x] = callbacks[x].getClass();
      }
      // fixedInterceptorMap only populated at this point, after getCallbacks call above
      enhancer.setCallbackFilter(new ProxyCallbackFilter(
          this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
      enhancer.setCallbackTypes(types);

      // Generate the proxy class and create a proxy instance.
      return createProxyClassAndInstance(enhancer, callbacks);
    }
    catch (CodeGenerationException ex) {
      throw new AopConfigException("Could not generate CGLIB subclass of class [" +
          this.advised.getTargetClass() + "]: " +
          "Common causes of this problem include using a final class or a non-visible class",
          ex);
    }
    catch (IllegalArgumentException ex) {
      throw new AopConfigException("Could not generate CGLIB subclass of class [" +
          this.advised.getTargetClass() + "]: " +
          "Common causes of this problem include using a final class or a non-visible class",
          ex);
    }
    catch (Throwable ex) {
      // TargetSource.getTarget() failed
      throw new AopConfigException("Unexpected AOP exception", ex);
    }
}

自此完整的Spring Boot AOP生成了代理对象。在我们的代码示例中定义一个UserController类,如下图生成其代理对象,最终Spring Boot容器使用的就是这个代理对象。


图片选自我的公众号

DEBUG源码执行的顺序表

为了方便debug时快速找到具体的实现方法,把Spring Boot(版本1.5.7.RELEASE) AOP的调用顺序统计在下表中,方法中省略参数列表。


图片选自我的公众号
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,230评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,261评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,089评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,542评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,542评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,544评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,922评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,578评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,816评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,576评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,658评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,359评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,920评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,859评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,381评论 2 342

推荐阅读更多精彩内容