spring bean初始化源码阅读

启动容器

下面以注解方式启动容器,进行代码跟踪bean的初始化过程

String basePackages = "com.cpx.service";
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(basePackages);
UserService userService = (UserService) ctx.getBean("userServiceImpl");
userService.sayHello();
ctx.close();

这里使用AnnotationConfigApplicationContext进行构造容器扫描配置,下面是它的构造方法。1、调用无参构造函数初始化reader和scanner。2、扫描配置。将注解bean封装成一个BeanDefinition对象进行描述。3、实例化bean

public AnnotationConfigApplicationContext(String... basePackages) {
   this();//初始化reader和scanner
   //扫描指定包,寻找bean
   scan(basePackages);
   //实例化bean
   refresh();
}

public AnnotationConfigApplicationContext() {
  this.reader = new AnnotatedBeanDefinitionReader(this);
  createAnnotatedBeanDefReader.end();
  this.scanner = new ClassPathBeanDefinitionScanner(this);
}

扫描bean定义

扫描实际操作是在ClassPathBeanDefinitionScanner.doScan方法

protected Set doScan(String... basePackages) {
   Set beanDefinitions = new LinkedHashSet<>();
   for (String basePackage : basePackages) {//循环所有指定的包路径
      //step1 找到所有可能的bean
      Set candidates = findCandidateComponents(basePackage);
      for (BeanDefinition candidate : candidates) {
         //读取@Scope设置,默认是singleton
         ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
         candidate.setScope(scopeMetadata.getScopeName());
         //获取beanName,首先根据注解判断是否明确指定,否则根据beanDef自动生成
         String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
         //这里candidate实例是ScannedGenericBeanDefinition,下面两个if都成立
         if (candidate instanceof AbstractBeanDefinition) {
            postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
         }
         if (candidate instanceof AnnotatedBeanDefinition) {
         //解析一些基本的注解配置 @Lazy @Primary @DependsOn @Role @Description
            AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
         }
         //检查beanname是否存在
         if (checkCandidate(beanName, candidate)) {
         // 构造BeanDefinitionHolder放到beanDefinitions中
            BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
            definitionHolder =
                  AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
            beanDefinitions.add(definitionHolder);
            //beanDefinition注册,不仅会按beanName注册,还会解析alias注册alias
            //最后会放到beanFacotry的beanDefinitionMap属性存储
            registerBeanDefinition(definitionHolder, this.registry);
         }
      }
   }
   return beanDefinitions;
}

step1查找所有的bean最后是在scanCandidateComponents方法

private Set scanCandidateComponents(String basePackage) {
   Set candidates = new LinkedHashSet<>();
      String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
            resolveBasePackage(basePackage) + '/' + this.resourcePattern;
      //step1 解析包下所有class文件资源
      Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
      for (Resource resource : resources) {//逐个判断是否是bean       
            MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
            //step2 判断是否包含指定的注解
            if (isCandidateComponent(metadataReader)) {//是bean,构造BeanDefinition
               ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
               sbd.setSource(resource);
               if (isCandidateComponent(sbd)) {//step3 判断
                  candidates.add(sbd);
               }
            }
      }
   return candidates;
}

step2处判断是否是bean条件

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
   for (TypeFilter tf : this.excludeFilters) {//默认excludeFilters是空
      if (tf.match(metadataReader, getMetadataReaderFactory())) {
         return false;
      }
   }
   //默认includeFilters是 org.springframework.stereotype.Component和javax.annotation.ManagedBean两个
   for (TypeFilter tf : this.includeFilters) {
      if (tf.match(metadataReader, getMetadataReaderFactory())) {
         return isConditionMatch(metadataReader);
      }
   }
   return false;
}

bean的实例化

beandef解析完成后,下一步就是对bean进行实例化。这里有 refresh方法开始

AbstractApplicationContext.refresh方法.这个方法在初始化的时候做了很多事情,这里先把完整方法放这里,

public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {

      // Prepare this context for refreshing.
      prepareRefresh();

      //这里实例是DefaultListableBeanFactory
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      prepareBeanFactory(beanFactory);

         // Allows post-processing of the bean factory in context subclasses.
         postProcessBeanFactory(beanFactory);

         StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
         //定义的BeanFactoryPostProcessor会在这里调用
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         registerBeanPostProcessors(beanFactory);
         beanPostProcess.end();

         // Initialize message source for this context.
         initMessageSource();

         // Initialize event multicaster for this context.
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         onRefresh();

         // Check for listener beans and register them.
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         finishRefresh();  
   }
}

最后bean的实例化在finishBeanFactoryInitialization(beanFactory);这一步里面。最后调用beanFactory.preInstantiateSingletons()方法实例化bean。就从这里开始看。

public void preInstantiateSingletons() throws BeansException {
   //获取所有解析的beanDefinitionNames
   List beanNames = new ArrayList<>(this.beanDefinitionNames);

   // Trigger initialization of all non-lazy singleton beans...
   for (String beanName : beanNames) {
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      //不是Abstract,是单例不是懒加载
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         if (isFactoryBean(beanName)) {//从工厂里获取一次,第一次肯定为null走else
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            if (bean instanceof FactoryBean) {
               FactoryBean factory = (FactoryBean) bean;
               boolean isEagerInit;
               if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                  isEagerInit = AccessController.doPrivileged(
                        (PrivilegedAction) ((SmartFactoryBean) factory)::isEagerInit,
                        getAccessControlContext());
               }
               else {
                  isEagerInit = (factory instanceof SmartFactoryBean &&
                        ((SmartFactoryBean) factory).isEagerInit());
               }
               if (isEagerInit) {
                  getBean(beanName);
               }
            }
         }
         else {
            getBean(beanName);
         }
      }
   }
   // ...
}

我们看到了熟悉的getBean方法。bean的实例化也是从这个方法开始的。

getBean方法的大致逻辑

AbstractBeanFacotry.getBean()

->doGetBean()

	case1->getSingleton(beanName, true)

	case2->getSingleton(beanName, ObjectFactory() {

			getObject(){ return createBean(beanName, mbd, args); }

	};

getBean方法实际会使用doGetBean方法进行获取bean。doGetBean首先从单例缓存中获取getSingleton(beanName, true),如果获取不到就调用getSingleton(beanName, ObjectFactory)方法,然后调用ObjectFactory.getObject方法,最后是createBean方法。

bean的实例化,一个重要的类DefaultSingletonBeanRegistry

DefaultSingletonBeanRegistry{
   /** 已经实例化好的单例bean  */
	private final Map singletonObjects = new ConcurrentHashMap<>(256);

	/**半成品bean   */
	private final Map> singletonFactories = new HashMap<>(16);

	/** 三级缓存 */
	private final Map earlySingletonObjects = new ConcurrentHashMap<>(16);

	/** 正在创建的beanName集合 */
	private final Set singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));
}

重要的方法getSingleton

/**
  allowEarlyReference 是否从早期引用中查找,也就是从二三级缓存查找
*/
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   //一级缓存是否存在
   Object singletonObject = this.singletonObjects.get(beanName);
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {//不在一级缓存且在正在创建列表中
      singletonObject = this.earlySingletonObjects.get(beanName);//三级缓存是否存在
      if (singletonObject == null && allowEarlyReference) {
         synchronized (this.singletonObjects) {
            // 二次检查一级缓存是否存在
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               singletonObject = this.earlySingletonObjects.get(beanName);//三级缓存是否存在
               if (singletonObject == null) {
                  //二级缓存中拿出factory
                  ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
                  if (singletonFactory != null) {
                     // 调用factory的getObject方法,会调用实现的getEarlyBeanReference方法
                     singletonObject = singletonFactory.getObject();
                     this.earlySingletonObjects.put(beanName, singletonObject);//放入三级缓存
                     this.singletonFactories.remove(beanName);//二级缓存中移除
                  }
               }
            }
         }
      }
   }
   return singletonObject;
}

上面getBean方法case2的getSingleton方法

1、还是先从singletonObjects缓存中查询是否有该bean。调用getSingleton(beanName,true)。第二个参数标识是是否从早期半成品缓存存中查找该bean。如果从二级缓存命中,回调用factory的getObject方法。最后会调用到getEarlyBeanReference方法。然后将其从二级缓存移除,加入到三级缓存中。

2、没有,先将当前bean加入到正在创建列表singletonsCurrentlyInCreation中。

3、然后调用入参ObjectFactory的getObject()方法,这里上面看到入参getObject的实现最终会调用createBean方法。createBean方法最后调用doCreateBean进行bean实例的创建。

4、调用afterSingletonCreation方法将当前bean从正在创建列表删除

5、调用addSingleton方法将当前实例加到一级缓存,然后二级、三级缓存中移除。

来看AbstractAutowireCapableBeanFactory.doCreateBean方法

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {//创建bean实例
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   Object bean = instanceWrapper.getWrappedInstance();
   Class beanType = instanceWrapper.getWrappedClass();
   //...

   // Eagerly cache singletons to be able to resolve circular references
   //是否满足早期暴露条件
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {
	//加入到二级缓存
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }

   // Initialize the bean instance.
   Object exposedObject = bean;
   try {//bean初始化 属性赋值
      populateBean(beanName, mbd, instanceWrapper);
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
   //...
   return exposedObject;
}

1、调用createBeanInstance方法根据beanDef进行对象实例化,这里就是根据反射先实例化,属性还未赋值

2、判断bean是否是earlySingletonExposure。判断条件:bean是单例,bean在正在创建列表singletonsCurrentlyInCreation中,当前spring支持循环依赖

如果条件成立,调用addSingletonFactory(beanName,ObjectFactory(){

getObject(){ getEarlyBeanReference(beanName, mbd, bean);}

})。

addSingletonFactory方法的具体实现就是将bean放入二级缓存singletonFactories中

3、populateBean方法对属性进行注入

这里就是依赖注入的地方,假如是a和b两个相互依赖,第一开始创建a走到这里,进行a的属性注入,也就是b。这时候获取b肯定还是从getBean(b)开始从头开始走。一步步走又走到这里进行b的属性注入,这个时候getBean(a)会调用到getSingleton(a, true)能够获取到a的实例,因为这个时候a在二级缓存中。所以b.a属性可以直接赋值。最后b创建成功,然后又回到a的populateBean里。a.b也赋值成功。

为什么三级缓存?

三级缓存主要是为了保持不同状态的bean实例。一级缓存是已经初始化好的bean。二级缓存是只是实例化,还未完成属性初始化,但是可以提前暴露给其它bean作为依赖属性进行注入。三级缓存是存储还未初始化完并且已经被其它bean引用到的。

你可能感兴趣的:(spring,spring,java,后端)