• Spring 源码(10)Spring Bean 的创建过程(1)


    Spring Bean的创建刚开始进行了一些准备工作,比如转换服务的初始化,占位符解析器的初始化,BeanDefinition元数据的冻结等操作,都是为了在创建Bean的过程中保证Bean的正确的创建,接下来开始进行对Bean的创建进行解析。

    Bean 的创建步骤

    Spring源码中对Bean的创建遵循一个步骤就是:getBean --> doGetBean --> createBean --> doCreateBean ,常规的Bean的创建过程都是按照这个步骤执行,然后反射实例化,属性填充,初始化,放到一级缓存中。那么非常规的有可能就不遵循这个步骤,比如FactoryBeanInstantiationAwareBeanPostProcessor 等。

    上源码:

    public void preInstantiateSingletons() throws BeansException {
      if (logger.isTraceEnabled()) {
        logger.trace("Pre-instantiating singletons in " + this);
      }
    
      // Iterate over a copy to allow for init methods which in turn register new bean definitions.
      // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
      List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    
      // Trigger initialization of all non-lazy singleton beans...
      // 遍历所有的beanName
      for (String beanName : beanNames) {
        // 获取RootBeanDefinition 从缓存中,第一个放入缓存是在 AbstractApplicationContext#invokeBeanFactoryPostProcessors 中的getBeanNamesForType方法中
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        // 如果不是抽象的,是单例的,是非懒加载的,则进行bean的创建,否则直接跳过
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
          // 是否是FactoryBean
          if (isFactoryBean(beanName)) {
            // 获取bean实例
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            // 判断获取的Bean是否是FactoryBean
            if (bean instanceof FactoryBean) {
              FactoryBean<?> factory = (FactoryBean<?>) bean;
              // 是否是饥饿初始化,默认是false
              boolean isEagerInit;
              // 权限校验
              if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                isEagerInit = AccessController.doPrivileged(
                  (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                  getAccessControlContext());
              }
              else {
                isEagerInit = (factory instanceof SmartFactoryBean &&
                               ((SmartFactoryBean<?>) factory).isEagerInit());
              }
              // 如果是饥饿初始化,则进行bean的创建
              if (isEagerInit) {
                getBean(beanName);
              }
            }
          }
          else {
            // 获取bean
            getBean(beanName);
          }
        }
      }
    
      // Trigger post-initialization callback for all applicable beans...
      // 触发 所有Bean初始化后的回调
      for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        // 获取单例对象,如果是SmartInitializingSingleton 则调用afterSingletonsInstantiated
        // 在监听器中使用@EventListener注解标记的方法就是在这个方法中进行监听器的添加的,会创建一个监听器的适配器
        // 调用类为 EventListenerMethodProcessor
        if (singletonInstance instanceof SmartInitializingSingleton) {
          SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
          // 权限检查
          if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
              smartSingleton.afterSingletonsInstantiated();
              return null;
            }, getAccessControlContext());
          }
          else {
            smartSingleton.afterSingletonsInstantiated();
          }
        }
      }
    }
    

    通过源码可以知道,Spring前期在进行XML进行loadBeanDefinitions加载或者BeanFactoryPostProcessor子类BeanDefinitionRegistryPostProcessor的实现类ConfigurationClassPostProcessor注解解析 出来的BeanDefinition放入两个集合BeanDefinitionMapBeanDefinitionNames,这里遍历的是BeanDefinitionNames这个集合,存放的是beanName

    首先是进行了BeanDefinition的合并处理,最终返回的全是RootBeanDefinition,进入源码可以看到这里是从缓存中获取的,如果有则直接取出来,否则再去解析。

    protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
      // Quick check on the concurrent map first, with minimal locking.
      // 从缓存中获取
      RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
      if (mbd != null && !mbd.stale) {
        return mbd;
      }
      return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
    }
    

    那么第一次进行调用时什么地方呢?是在进行BeanFactoryPostProcessor 的执行和解析时调用的,在解析BeanFactoryPostProcessor时调用了 getBeanNamesForType方法,然后调用doGetBeanNamesForType时进行了BeanDefinitionNames集合的遍历合并Bean

    private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
      List<String> result = new ArrayList<>();
      // Check all bean definitions.
      // 遍历所有的BeanDefinitionNames集合
      for (String beanName : this.beanDefinitionNames) {
        // Only consider bean as eligible if the bean name is not defined as alias for some other bean.
        if (!isAlias(beanName)) {
          try {
            // 从本地缓存中获取合并的BeanDefinition
            RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // Only check bean definition if it is complete.
            if (!mbd.isAbstract() && (allowEagerInit ||
                                      (mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
                                      !requiresEagerInitForType(mbd.getFactoryBeanName()))) {
              // 是否是FactoryBean
              boolean isFactoryBean = isFactoryBean(beanName, mbd);
              BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
              boolean matchFound = false;
              boolean allowFactoryBeanInit = (allowEagerInit || containsSingleton(beanName));
              boolean isNonLazyDecorat
                // 省略代码....
            }
          }
        }
      }
    
    

    所以在执行preInstantiateSingletons 预实例化单例时获取的RootBeanDefinition基本是从缓存中获取的。

    接着是判断如果是单例的并且不是抽象的,不是懒加载的,那么就进行Bean的创建,然后又判断是否是FactoryBean,如果是那么就进行下一步逻辑。

    FactoryBean 是什么?

    FactoryBean是用来创建Bean对象的,他是一个接口,方法:

    • getObject 获取bean对象
    • getObjectType 获取bean的类型
    • isSingleton 是否是单例的,默认是true

    在创建对象时,你可以直接在getObject方法中进行new,或者反射,或者是其他都可以,非常的灵活。接下来使用FactoryBean进行自定义的Bean的创建。

    定义一个FactoryBean的实现类:

    /**
     * @author <a href="https://www.cnblogs.com/redwinter/">redwinter</a>
     * @since 1.0
     **/
    public class MyFactoryBean implements FactoryBean<MyUser> {
    
    	@Override
    	public MyUser getObject() throws Exception {
          	// 直接new一个对象
    		return new MyUser();
    	}
    
    	@Override
    	public Class<?> getObjectType() {
    		return MyUser.class;
    	}
    
    	@Override
    	public boolean isSingleton() {
    		return true;
    	}
    }
    

    定义MyUser

    /**
     * @author <a href="https://www.cnblogs.com/redwinter/">redwinter</a>
     * @since 1.0
     **/
    public class MyUser {
    }
    
    

    xml配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:context="http://www.springframework.org/schema/context"
          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
       <bean id="myFactoryBean" class="com.redwinter.selffactorybean.MyFactoryBean"/>
    </beans>
    

    测试类:

    /**
     * @author <a href="https://www.cnblogs.com/redwinter/">redwinter</a>
     * @since 1.0
     **/
    public class FactoryBeanTest {
    
    	@Test
    	public void test(){
    		MyClassPathXmlApplicationContext context = new MyClassPathXmlApplicationContext("spring-factory.xml");
    
    		Object myFactoryBean =  context.getBean("myFactoryBean");
    		System.out.println(myFactoryBean);
    
    		Object myFactoryBean2 =  context.getBean("&myFactoryBean");
    		System.out.println(myFactoryBean2);
    
    	}
    }
    

    输出:

    com.redwinter.test.selffactorybean.MyUser@2d554825
    com.redwinter.test.selffactorybean.MyFactoryBean@68837a77
    

    这里可以看到FactoryBean 创建Bean的时候,xml注册的是一个FactoryBean的实现,但是获取出来又是具体的MyUser对象,这里Spring使用了懒加载的机制,在SpringBean进行初始化时,实际上只将FactoryBean的实现类注册到了Spring容器中,当我们需要使用的时候,才去判断,如果是FactoryBean类型的,那么就去调用getObject方法去创建对象。如果是第二次去获取Bean,那么是从缓存中获取的,如果是获取&前缀的Bean,那就直接返回。

    protected Object getObjectForBeanInstance(
      Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    
      // Don't let calling code try to dereference the factory if the bean isn't a factory.
      // 判断是否是&前缀标识
      if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
          return beanInstance;
        }
        if (!(beanInstance instanceof FactoryBean)) {
          throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
        }
        if (mbd != null) {
          mbd.isFactoryBean = true;
        }
        return beanInstance;
      }
    
      // Now we have the bean instance, which may be a normal bean or a FactoryBean.
      // If it's a FactoryBean, we use it to create a bean instance, unless the
      // caller actually wants a reference to the factory.
      if (!(beanInstance instanceof FactoryBean)) {
        return beanInstance;
      }
    
      Object object = null;
      if (mbd != null) {
        mbd.isFactoryBean = true;
      }
      else {
        // 从缓存中获取
        object = getCachedObjectForFactoryBean(beanName);
      }
      if (object == null) {
        // Return bean instance from factory.
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        if (mbd == null && containsBeanDefinition(beanName)) {
          mbd = getMergedLocalBeanDefinition(beanName);
        }
        // 判断是否是合成的Bean,是否是应用程序本身设置的,比如某些aop 就是合成的Bean
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        // 执行getObject方法获取Bean
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
      }
      return object;
    }
    

    BeanFactory 和FactoryBean 的区别?

    根据前面的文章介绍,我们知道BeanFactory是一个Bean的创建工厂,比如AbstractApplicationContext就是BeanFactory的实现类,这个类就是用来创建Bean的,创建出来的Bean放在缓存中。而FactoryBean就是Bean实例,是由BeanFactory创建的,并且FactoryBean也是用来创建Bean对象,使用getObject方法进行创建,也是会放在缓存中供下次直接获取,而且如果在使用时需要使用FactoryBean的实例时需要以&前缀才能获取到,比如getBean("&myFactoryBean"); 如果是获取通过getObject方法创建的对象时,就不需要添加&前缀,比如getBean("myFactoryBean"); 总结一下:

    相同点:

    • 都是用来创建对象的
    • 都是创建出来之后放入缓存中供下次直接使用

    不同点:

    • BeanFactory是一个对象创建工厂,而FactoryBean是一个Bean实例
    • BeanFactory创建的对象一般来说都是使用反射调用构造函数创建的,而FactoryBean创建对象是调用getObject方法创建,并且创建方式不一定是通过反射,可以是直接new对象或者其他方式
    • FactoryBean 在获取对象时,可以获取到两个对象,一个是存放在BeanFactory创建的缓存中,通过&beanName获取的FactoryBean的实现类对象,一个是调用getObject创建的,通过beanName获取的具体对象。

    Bean的创建过程非常复杂,下一篇继续。

  • 相关阅读:
    基于单片机的贪吃蛇设计
    TCP/IP(二)导论
    NCV7724DQBR2G车规级半桥电机驱动芯片-专为汽车,工业自动化应用提供完美解决方案
    【色彩管理】色彩管理之灰平衡
    第九章 更复杂的光照
    AI企业盈利与成本问题
    投研报告 -用DEX技术链改投注网站的项目Betswap($BSGG)
    【CTO变形记】有序定无序—为什么越努力,越无力
    Comparing Top-Down and Bottom-Up Design Approaches
    已解决:云原生领域的超时挂载Bug — Kubernetes深度剖析
  • 原文地址:https://www.cnblogs.com/redwinter/p/16251260.html