创建目标类的代理对象过程

步骤1

finishBeanFactoryInitialization(beanFactory), 完成BeanFactory的初始化工作,就是来创建剩下的单实例bean,

在创建的过程中就会被各个后置处理器拦截掉,下面我们就看看finishBeanFactoryInitialization(beanFactory);


步骤2

进入到 finishBeanFactoryInitialization(beanFactory)中,就会看到来到 beanFactory.preInstantiateSingletons()创建bean

进入preInstantiateSingletons()方法中,看到在循环所有bean创建对象,通过getBean(beanName)创建

最后来到doGetBean(name, null, null, false)方法,首先检查单实例的缓存中是否存在当前对象

如果存在就直接返回,否则就通过调用 getSingleton()获得单实例bean,只要创建好的bean就会被缓存起来,保证单实例bean

之后调用createBean(beanName,mbd,args)创建bean

进入到createBean()后就会调用resolveBeforeInstantiation(beanName, mbdToUse)方法,


希望后置处理器再此能返回一个代理对象,如果能返回就是使用,否则就调用下面的doCreateBean()创建,对于doCreateBean()方法之前已经详细介绍过了,


就是先创建bean实例,然后为bean属性赋值,然后在调用bean的init方法前后调用后置处理器等等操作。

我们来到 resolveBeforeInstantiation(beanName, mbdToUse)中, 给目标对象一个创建一个代理的机会

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    // 检查是否尚未确定不需要在实例化前解析
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // 确保此时 bean 类已经被解析
        // 如果不是合成 bean 且存在 InstantiationAwareBeanPostProcessor
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            // 确定目标 bean 的类型
            Class<?> targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                // 应用实例化前的 BeanPostProcessor
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    // 如果成功创建了 bean,则应用初始化后的处理器
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        // 标记是否成功在实例化前解析了 bean
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}

先调用 applyBeanPostProcessorsBeforeInstantiation(targetType, beanName)方法,进入其中,看到

先循环所有后置处理器,判断是不是InstantiationAwareBeanPostProcessor类型的后置处理器,


如果是就调用它的postProcessBeforeInstantiation(beanClass, beanName)方法,


而我们之前已经说过AnnotationAwareAspectJAutoProxyCreatorSmartInstantiationAwareBeanPostProcessor类型的后置处理器,


SmartInstantiationAwareBeanPostProcessor又继承了InstantiationAwareBeanPostProcessor


所以AnnotationAwareAspectJAutoProxyCreator也就是InstantiationAwareBeanPostProcessor这种类型的后置处理器,


最后就会调用AnnotationAwareAspectJAutoProxyCreatorpostProcessBeforeInstantiation()方法,


我们就来看看postProcessBeforeInstantiation()方法都干了些啥?


步骤3

现在我们就关心我们自己创建的LogAspect和MathCal是怎样创建的?我们的MathCal来到


org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(Class<?>, String)方法


(AnnotationAwareAspectJAutoProxyCreator中没有postProcessBeforeInstantiation()方法的实现,只能调用父类的方法),


首先判断是否在advisedBeans中,advisedBeans中保存了所有需要增强的目标对象bean。第一次创建是不会包含的,所有 if 没进去。

然后就来到第二个判断,首先判断当前bean是否是基础类型即判断是否是实现了Advice,Pointcut,Advisor,AopInfrastructureBean

这几个接口,其次还会判断是否是加了@Aspect注解的

最后再通过shouldSkip(beanClass, beanName)判断是否需要跳过

/**
 * 判断是否应该跳过对指定 Bean 类和 Bean 名称的处理。
 *
 * @param beanClass Bean 的类对象
 * @param beanName  Bean 的名称
 * @return 如果应该跳过处理则返回 true,否则返回 false
 */
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    // 待办事项:考虑通过缓存切面名称列表来进行优化
    // 查找所有候选的 Advisor(通知器)
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 遍历所有候选的 Advisor
    for (Advisor advisor : candidateAdvisors) {
        // 检查当前 Advisor 是否为 AspectJ 切点通知器
        if (advisor instanceof AspectJPointcutAdvisor) {
            // 获取该 Advisor 中的通知,并将其转换为 AbstractAspectJAdvice 类型
            // 然后获取切面的名称,并与当前 Bean 的名称进行比较
            if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
                // 如果切面名称与 Bean 名称相等,则表示应该跳过对该 Bean 的处理
                return true;
            }
        }
    }
    // 如果没有匹配到需要跳过的情况,则调用父类的 shouldSkip 方法进行判断
    return super.shouldSkip(beanClass, beanName);
}

在shouldSkip()中首先获得四个增强器即切面中的四个通知方法,将通知方法包装为InstantiationModelAwarePointcutAdvisor类型的,


判断增强器是否是AspectJPointcutAdvisor类型的,而我们的类型不是,就会调用父类的super.shouldSkip(beanClass, beanName);


返回false,最后就返回null,继续 doCreateBean(beanName, mbdToUse, args)-->createBeanInstance(beanName, mbd, args)

-->populateBean(beanName, mbd, instanceWrapper)-->initializeBean(beanName, exposedObject, mbd)-->applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)


之后又来到org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(Object, String)方法

调用 wrapIfNecessary(bean, beanName, cacheKey) 进入其中

  /**
   * 如果有必要,对指定的 Bean 进行包装(创建代理)。
   *
   * @param bean     要检查并可能包装的 Bean 实例
   * @param beanName Bean 的名称
   * @param cacheKey 用于缓存的键,代表当前 Bean 的唯一标识
   * @return 如果需要,返回包装后的代理对象;否则返回原始的 Bean 实例
   */
  protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
      // 检查 beanName 是否不为空,并且 targetSourcedBeans 集合中包含该 beanName
      // 如果是,则表示该 Bean 已经由 TargetSource 处理过,不需要再进行包装,直接返回原始 Bean
      if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
          return bean;
      }
      // 从 advisedBeans 缓存中获取当前 Bean 对应的处理标记
      // 如果标记为 false,表示该 Bean 不需要被代理,直接返回原始 Bean
      if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
          return bean;
      }
      // 检查该 Bean 的类是否为基础设施类(如 Spring 内部使用的类),或者是否应该跳过该 Bean 的处理
      // 如果是,则将该 Bean 的处理标记为 false 并放入 advisedBeans 缓存中,然后返回原始 Bean
      if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
          this.advisedBeans.put(cacheKey, Boolean.FALSE);
          return bean;
      }

      // 如果存在通知(Advice),则创建代理
      // 获取该 Bean 对应的通知和通知器数组
      Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
      // 如果获取到的通知和通知器数组不为 DO_NOT_PROXY(表示需要进行代理)
      if (specificInterceptors != DO_NOT_PROXY) {
          // 将该 Bean 的处理标记为 true 并放入 advisedBeans 缓存中
          this.advisedBeans.put(cacheKey, Boolean.TRUE);
          // 创建代理对象
          Object proxy = createProxy(
                  bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
          // 将代理对象的类型放入 proxyTypes 缓存中
          this.proxyTypes.put(cacheKey, proxy.getClass());
          // 返回代理对象
          return proxy;
      }

      // 如果不需要进行代理,将该 Bean 的处理标记为 false 并放入 advisedBeans 缓存中
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      // 返回原始 Bean
      return bean;
  }

获取所有候选增强器,然后通过切点表达式进行筛选,获得与其当前匹配的bean增强器(通知方法),如何获取呢?

通过 createProxy() 创建代理对象,最后保存当前bean到 advisedBeans中,表示当前bean已经增强

先根据 Bean 名称获取其对应的增强器(通知方法),保存到proxyFactory中,通过proxyFactory.getProxy(getProxyClassLoader()),获得代理对象

  /**
   * 创建指定 Bean 的代理对象。
   *
   * @param beanClass         Bean 的类对象,即要被代理的目标类
   * @param beanName          Bean 的名称,用于标识该 Bean
   * @param specificInterceptors 该 Bean 对应的特定拦截器和通知器数组
   * @param targetSource      目标对象的源,用于获取实际的目标对象
   * @return 创建好的代理对象
   */
  protected Object createProxy(
          Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

      // 检查当前的 Bean 工厂是否为 ConfigurableListableBeanFactory 类型
      if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
          // 如果是,则通过 AutoProxyUtils 工具类暴露目标类信息到 Bean 工厂中
          // 这有助于在某些情况下让其他组件知道目标类的实际类型
          AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
      }

      // 创建一个 ProxyFactory 实例,用于创建代理对象
      ProxyFactory proxyFactory = new ProxyFactory();
      // 将当前对象的配置信息复制到 ProxyFactory 中
      // 确保代理工厂使用相同的配置
      proxyFactory.copyFrom(this);

      // 检查 ProxyFactory 是否已经配置为代理目标类(使用 CGLIB 代理)
      if (!proxyFactory.isProxyTargetClass()) {
          // 如果没有配置为代理目标类,则检查是否应该代理目标类
          if (shouldProxyTargetClass(beanClass, beanName)) {
              // 如果应该代理目标类,则将 ProxyFactory 的配置设置为代理目标类
              proxyFactory.setProxyTargetClass(true);
          } else {
              // 否则,评估目标类实现的接口,根据接口情况来配置代理方式
              evaluateProxyInterfaces(beanClass, proxyFactory);
          }
      }

      // 根据 Bean 名称获取其对应的增强器
      Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);

      // 将构建好的增强器添加到 ProxyFactory 中
      proxyFactory.addAdvisors(advisors);

      // 设置目标对象(被代理对象)
      proxyFactory.setTargetSource(targetSource);

      // 对 ProxyFactory 进行自定义配置,允许子类进行额外的定制
      customizeProxyFactory(proxyFactory);

      // 设置 ProxyFactory 是否冻结代理配置
      // 如果冻结,则在创建代理后不能再修改代理的配置
      proxyFactory.setFrozen(this.freezeProxy);
      // 检查通知器是否已经预先过滤
      if (advisorsPreFiltered()) {
          // 如果已经预先过滤,则设置 ProxyFactory 为预过滤状态
          proxyFactory.setPreFiltered(true);
      }

      // 使用 ProxyFactory 创建代理对象,并指定代理类加载器
      return proxyFactory.getProxy(getProxyClassLoader());
  }

进入其中

  /**
   * 根据提供的 AOP 配置信息创建 AOP 代理对象。
   *
   * @param config 包含 AOP 代理配置的 AdvisedSupport 对象
   * @return 一个 AopProxy 实例,用于生成具体的 AOP 代理对象
   * @throws AopConfigException 如果配置信息不符合代理创建要求,抛出此异常
   */
  public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
      // 检查是否满足使用 CGLIB 代理的条件:
      // 1. 是否开启了优化选项
      // 2. 是否明确指定使用目标类代理
      // 3. 是否没有用户提供的代理接口
      if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
          // 获取目标类的 Class 对象
          Class<?> targetClass = config.getTargetClass();
          // 如果目标类为 null,说明无法确定目标类,抛出 AopConfigException 异常
          if (targetClass == null) {
              throw new AopConfigException("TargetSource cannot determine target class: " +
                      "Either an interface or a target is required for proxy creation.");
          }
          // 如果目标类是接口或者是代理类,使用 JDK 动态代理
          if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
              return new JdkDynamicAopProxy(config);
          }
          // 否则,使用 ObjenesisCglibAopProxy(基于 CGLIB 的代理)
          return new ObjenesisCglibAopProxy(config);
      } else {
          // 如果不满足使用 CGLIB 代理的条件,默认使用 JDK 动态代理
          return new JdkDynamicAopProxy(config);
      }
  }

spring自动决定使用JDK方式代理还是使用Cglib方式代理

至此就创建出代理对象啦,并返回回去了,以后容器中拿到的就是代理对象了,接下来拿到代理对象,如何调用增强方法

posted @ 2025-03-25 23:52  jock_javaEE  阅读(19)  评论(0)    收藏  举报