Spring Bean的创建过程及相关扩展点(上)

简介: Spring Bean的创建过程及相关扩展点

首先,我们最基本的常识是从ApplicationContext入手,从AbstractApplicationContext的refresh()作为入口,找到finishBeanFactoryInitialization()方法,这个方法的作用是实例化非懒加载的Bean实例。那么我们就可以进入AbstractBeanFactory的getBean()方法。

@Override
  public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
  }
  @Override
  public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
    return doGetBean(name, requiredType, null, false);
  }
  @Override
  public Object getBean(String name, Object... args) throws BeansException {
    return doGetBean(name, null, args, false);
  }
复制代码

下面来看看doGetBean()方法:

protected <T> T doGetBean(
      String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
      throws BeansException {
    // 转换一下,比如有别名、&开头的名字等这些请求,全部都转换成统一的beanName
    String beanName = transformedBeanName(name);
    Object bean;
    // Eagerly check singleton cache for manually registered singletons.
    // 从缓存中去。先从一级缓存中取,不行再从二级缓存取、最后从三级缓存取
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
      if (logger.isTraceEnabled()) {
        if (isSingletonCurrentlyInCreation(beanName)) {
          logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
              "' that is not fully initialized yet - a consequence of a circular reference");
        }
        else {
          logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
        }
      }
      // 扩展点---------扩展点-----------扩展点-------------
      // 判断name是不是&开头的,如果是&开头的话,并且sharedInstance是FactoryBean类型,就直接返回
      // 如果不是&开头,也不是FactoryBean类型,直接返回
      // 如果不是&开头,是FactoryBean类型,调用getObject()方法返回Bean对象
      // 也就是说,我们可以通过实现FactoryBean来创建Bean对象
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    else {
      // Fail if we're already creating this bean instance:
      // We're assumably within a circular reference.
      if (isPrototypeCurrentlyInCreation(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
      }
      // 下面是从父容器中找对应的Bean实例
      // 注意:容器是存在父子关系的。spring mvc就是一个父子关系的容器
      // Check if bean definition exists in this factory.
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
        // Not found -> check parent.
        String nameToLookup = originalBeanName(name);
        if (parentBeanFactory instanceof AbstractBeanFactory) {
          return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
              nameToLookup, requiredType, args, typeCheckOnly);
        }
        else if (args != null) {
          // Delegation to parent with explicit args.
          return (T) parentBeanFactory.getBean(nameToLookup, args);
        }
        else if (requiredType != null) {
          // No args -> delegate to standard getBean method.
          return parentBeanFactory.getBean(nameToLookup, requiredType);
        }
        else {
          return (T) parentBeanFactory.getBean(nameToLookup);
        }
      }
      if (!typeCheckOnly) {
        markBeanAsCreated(beanName);
      }
      // 下面准备查找当前Bean对象依赖的其他Bean。比如在创建当前这个Bean之前必须要创建另外一个Bean
      try {
        RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
        checkMergedBeanDefinition(mbd, beanName, args);
        // 找到所有在这个Bean创建之前一定要创建出来的依赖,依次调用getBean()创建
        // Guarantee initialization of beans that the current bean depends on.
        String[] dependsOn = mbd.getDependsOn();
        if (dependsOn != null) {
          for (String dep : dependsOn) {
            if (isDependent(beanName, dep)) {
              throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
            }
            registerDependentBean(dep, beanName);
            try {
              getBean(dep);
            }
            catch (NoSuchBeanDefinitionException ex) {
              throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
            }
          }
        }
        // Create bean instance.
        if (mbd.isSingleton()) {
          // ******这是重点******这是重点******这是重点******这是重点******
          // 这里理解起来有点绕。注意这个getSingleton(String beanName,ObjectFactory<?> singletonFactory)方法。
          // 第二个参数使用lamble表达式,可以先忽略
          // getSingleton()里面就做了两件事情:
          // 1.通过lamble表达式创建Bean对象
          // 2.把创建好的Bean对象放到一级缓存中
          // 最后返回创建好的Bean对象
          sharedInstance = getSingleton(beanName, () -> {
            try {
              // 一定要先理清楚getSingleton()方法,再来看createBean()方法
              // ******这是重点******这是重点******这是重点******这是重点*****
              return createBean(beanName, mbd, args);
            }
            catch (BeansException ex) {
              // Explicitly remove instance from singleton cache: It might have been put there
              // eagerly by the creation process, to allow for circular reference resolution.
              // Also remove any beans that received a temporary reference to the bean.
              // 没创建成功就要销毁。不是重点
              destroySingleton(beanName);
              throw ex;
            }
          });
          // 同样的,检查一下是不是FactoryBean,并且name是否以&开头
          // 扩展点---------扩展点-----------扩展点-------------
          // 判断name是不是&开头的,如果是&开头的话,并且sharedInstance是FactoryBean类型,就直接返回
          // 如果不是&开头,也不是FactoryBean类型,直接返回
          // 如果不是&开头,是FactoryBean类型,调用getObject()方法返回Bean对象
          // 也就是说,我们可以通过实现FactoryBean来创建Bean对象
          bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }
        // 其实到这里就可以不用看非单例的情况了,因为基本都差不多。重点关注如何创建Bean对象。
        else if (mbd.isPrototype()) {
          // It's a prototype -> create a new instance.
          Object prototypeInstance = null;
          try {
            beforePrototypeCreation(beanName);
            // 还是创建Bean对象,这是重点
            // ******这是重点******这是重点******这是重点******这是重点*****
            prototypeInstance = createBean(beanName, mbd, args);
          }
          finally {
            afterPrototypeCreation(beanName);
          }
          // 同上,检查是否是FactoryBean
          bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
        }
        // 这里也一样,其他scope,重点还是在createBean()
        else {
          String scopeName = mbd.getScope();
          if (!StringUtils.hasLength(scopeName)) {
            throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
          }
          Scope scope = this.scopes.get(scopeName);
          if (scope == null) {
            throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
          }
          try {
            Object scopedInstance = scope.get(beanName, () -> {
              beforePrototypeCreation(beanName);
              try {
                // 重点都在这里
                // ******这是重点******这是重点******这是重点******这是重点*****
                return createBean(beanName, mbd, args);
              }
              finally {
                afterPrototypeCreation(beanName);
              }
            });
            bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
          }
          catch (IllegalStateException ex) {
            throw new BeanCreationException(beanName,
                "Scope '" + scopeName + "' is not active for the current thread; consider " +
                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                ex);
          }
        }
      }
      catch (BeansException ex) {
        cleanupAfterBeanCreationFailure(beanName);
        throw ex;
      }
    }
  //下面都不是重点,可忽略
    // Check if required type matches the type of the actual bean instance.
    if (requiredType != null && !requiredType.isInstance(bean)) {
      try {
        T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
        if (convertedBean == null) {
          throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
        return convertedBean;
      }
      catch (TypeMismatchException ex) {
        if (logger.isTraceEnabled()) {
          logger.trace("Failed to convert bean '" + name + "' to required type '" +
              ClassUtils.getQualifiedName(requiredType) + "'", ex);
        }
        throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
    }
    return (T) bean;
  }
复制代码

下面简单分析一下getSingleton():

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    synchronized (this.singletonObjects) {
      // 先从一级缓存中取,先试试
      Object singletonObject = this.singletonObjects.get(beanName);
      if (singletonObject == null) {
        if (this.singletonsCurrentlyInDestruction) {
          throw new BeanCreationNotAllowedException(beanName,
              "Singleton bean creation not allowed while singletons of this factory are in destruction " +
              "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
        }
        if (logger.isDebugEnabled()) {
          logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
        }
        // 这不用看,就是做一个数据校验
        beforeSingletonCreation(beanName);
        boolean newSingleton = false;
        boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
        if (recordSuppressedExceptions) {
          this.suppressedExceptions = new LinkedHashSet<>();
        }
        try {
          // ******这是重点******这是重点******这是重点******这是重点*****
          // 这里就是调用lamble表示式里面的逻辑了,千万要理清楚
          // lamble表达式里面就是做了createBean()的逻辑
          singletonObject = singletonFactory.getObject();
          newSingleton = true;
        }
        // 处理创建Bean对象出异常的情况,不用管
        catch (IllegalStateException ex) {
          // Has the singleton object implicitly appeared in the meantime ->
          // if yes, proceed with it since the exception indicates that state.
          singletonObject = this.singletonObjects.get(beanName);
          if (singletonObject == null) {
            throw ex;
          }
        }
        catch (BeanCreationException ex) {
          if (recordSuppressedExceptions) {
            for (Exception suppressedException : this.suppressedExceptions) {
              ex.addRelatedCause(suppressedException);
            }
          }
          throw ex;
        }
        finally {
          if (recordSuppressedExceptions) {
            this.suppressedExceptions = null;
          }
          afterSingletonCreation(beanName);
        }
        if (newSingleton) {
          // 最后就是把创建好的Bean对象放到一级缓存中。因为这个Bean对象已经是可以安全发布的了。
          addSingleton(beanName, singletonObject);
        }
      }
      // 返回创建好的Bean对象
      return singletonObject;
    }
  }
复制代码

核心重点createBean()方法:

@Override
  protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
    if (logger.isTraceEnabled()) {
      logger.trace("Creating instance of bean '" + beanName + "'");
    }
    RootBeanDefinition mbdToUse = mbd;
    // Make sure bean class is actually resolved at this point, and
    // clone the bean definition in case of a dynamically resolved Class
    // which cannot be stored in the shared merged bean definition.
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
    }
    // Prepare method overrides.
    try {
      mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
          beanName, "Validation of method overrides failed", ex);
    }
    try {
      // ********重点1,这是一个扩展点,此时还没有任何Bean实例被创建出来
      // ********这里就是把Bean的创建机会开放给开发者
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
        return bean;
      }
    }
    catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
          "BeanPostProcessor before instantiation of bean failed", ex);
    }
    try {
      // 如果开发者自己不创建Bean对象,那么就spring自己来亲自处理
      // 重点2,这是spring框架创建Bean的过程
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isTraceEnabled()) {
        logger.trace("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
      // A previously detected exception with proper bean creation context already,
      // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
      throw ex;
    }
    catch (Throwable ex) {
      throw new BeanCreationException(
          mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
  }
复制代码

扩展点1:开发者自己创建Bean

@Nullable
  protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
      // Make sure bean class is actually resolved at this point.
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        Class<?> targetType = determineTargetType(beanName, mbd);
        if (targetType != null) {
          // 这里就是创建Bean的入口
          bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
          if (bean != null) {
            // 如果真的把Bean实例创建出来了,那么再继续后续的生命周期的逻辑调用
            bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
          }
        }
      }
      mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
  }
@Nullable
  protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
      // 一定要是InstantiationAwareBeanPostProcessor的实现类,才会在Bean没有实例化的时候被调用
      if (bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
        if (result != null) {
          return result;
        }
      }
    }
    return null;
  }
@Override
  public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {
    Object result = existingBean;
    // 这里面可以对已经创建出来的Bean实例增强
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
      Object current = processor.postProcessAfterInitialization(result, beanName);
      if (current == null) {
        return result;
      }
      result = current;
    }
    return result;
  }
复制代码

1.实现了InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation()方法,就有机会自己创建Bean对象

2.实现了BeanPostProcessor接口的postProcessAfterInitialization()方法就能在Bean对象创建出来后,还有机会对创建出来的Bean对象进行增强或者扩展。注意:可以在这个点做AOP增强。



相关文章
|
1天前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
29天前
|
XML Java 数据格式
Spring从入门到入土(bean的一些子标签及注解的使用)
本文详细介绍了Spring框架中Bean的创建和使用,包括使用XML配置文件中的标签和注解来创建和管理Bean,以及如何通过构造器、Setter方法和属性注入来配置Bean。
59 9
Spring从入门到入土(bean的一些子标签及注解的使用)
|
2月前
|
缓存 安全 Java
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
从底层源码入手,通过代码示例,追踪AnnotationConfigApplicationContext加载配置类、启动Spring容器的整个流程,并对IOC、BeanDefinition、PostProcesser等相关概念进行解释
168 24
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
|
20天前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
2月前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
192 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
2月前
|
XML Java 数据格式
spring复习02,xml配置管理bean
详细讲解了Spring框架中基于XML配置文件管理bean的各种方式,包括获取bean、依赖注入、特殊值处理、属性赋值、集合类型处理、p命名空间、bean作用域及生命周期和自动装配。
spring复习02,xml配置管理bean
|
29天前
|
Java 开发者 Spring
Spring bean的生命周期详解!
本文详细解析Spring Bean的生命周期及其核心概念,并深入源码分析。Spring Bean是Spring框架的核心,由容器管理其生命周期。从实例化到销毁,共经历十个阶段,包括属性赋值、接口回调、初始化及销毁等。通过剖析`BeanFactory`、`ApplicationContext`等关键接口与类,帮助你深入了解Spring Bean的管理机制。希望本文能助你更好地掌握Spring Bean生命周期。
62 1
|
1月前
|
Java Spring
获取spring工厂中bean对象的两种方式
获取spring工厂中bean对象的两种方式
27 1
|
1月前
|
Java 开发者 Spring
Spring bean的生命周期详解!
本文详细介绍了Spring框架中的核心概念——Spring Bean的生命周期,包括实例化、属性赋值、接口回调、初始化、使用及销毁等10个阶段,并深入剖析了相关源码,如`BeanFactory`、`DefaultListableBeanFactory`和`BeanPostProcessor`等关键类与接口。通过理解这些核心组件,读者可以更好地掌握Spring Bean的管理和控制机制。
75 1
|
2月前
|
XML Java 数据格式
spring复习03,注解配置管理bean
Spring框架中使用注解配置管理bean的方法,包括常用注解的标识组件、扫描组件、基于注解的自动装配以及使用注解后的注意事项,并提供了一个基于注解自动装配的完整示例。
spring复习03,注解配置管理bean