精通 Spring 源码 (二) | 揭秘 Bean 的前世今生

一、前言

接下来,我们对 Bean 的扫描与注册进行探究,一个 Java 类是如何变成一个 Bean 的呢,它中间走过了怎样的历程,这就是我们本章所要讨论的问题。

二、源码分析

在进行分析前,各位胖友可以先看一下思维导图,该思维导图详细记录了源码的每一步流程,并且每一步都有详细的注释,在在线地址可以看到注释,如下:

点击浏览 Spring 源码思维导图

本次我们将对 refresh 方法进行分析,在这个方法里面有 12 个方法,分别做了不同的事,我们将一步一步进行揭秘。

在这里插入图片描述

1、prepareRefresh

这个方法包括准备工作,设置启动时间,是否激活标识位(容器是否可用),初始化属性源配置,不是很重要。

2、obtainFreshBeanFactory

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

准备工作,初始化Bean工厂,得到 beanFactory, DefaultListableBeanFactory 实现了 ConfigurableListableBeanFactory 严格来说,Bean 生命周期的开始。

3、prepareBeanFactory

prepareBeanFactory(beanFactory);

准备 Bean 工厂,Bean 声明周期的开始,下面是在这个方法里面做的一些重要的事。

//类加载器
beanFactory.setBeanClassLoader(getClassLoader());
//bean的表达式解释器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//Property和String的转化
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
//Spring 添加一个后置处理器,能够在bean中获得各种Aware (重要)
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

在这里添加了一个后置处理器 new ApplicationContextAwareProcessor(this),如果一个类实现了各种 Aware,就会拥有相对应的功能,这是对 Spring 进行扩展的方式。我们可以看一下,这个后置处理器中的一个非常重要的方法。

比如这个代码 instanceof ApplicationContextAware,一个 Bean 实现了 ApplicationContextAware这个接口,提供setter 方法,就能得到 applicationContext ,这就是真个Spring 环境,我们就可以在代码中动态注册和改变一个 Bean 的属性。

private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			//当一个对象实现了ApplicationContextAware对象只需要提供setter就能得到applicationContext
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

4、postProcessBeanFactory

这是一个空方法,Spring 后期可能会做扩展。

5、invokeBeanFactoryPostProcessors

重要的方法,实现了 Bean 的扫描与注册。

我们可以跟进这个方法,首先定义了两个 集合,具体作用注释给出了。

//存放程序员自己添加的实现了BeanFactoryPostProcessor的
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//存放程序员自己添加的实现了BeanDefinitionRegistryPostProcessor的
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

注意一个关键词,程序员自己添加的,何为自己添加,也就是自己定义一个类,然后实现 BeanFactoryPostProcessor 或者 BeanDefinitionRegistryPostProcessor 这两个接口,然后调用下面方法添加进去,加@Component 不算。

//自定义的后置处理器
//applicationContext.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());

紧接着,就会处理 实现了 BeanDefinitionRegistryPostProcessor 的类,调用 postProcessBeanDefinitionRegistry 这个方法,然后把 实现了 BeanFactoryPostProcessor 的类放到一个集合里面去。这里并没有处理。
PS: BeanFactoryPostProcessor 是 BeanDefinitionRegistryPostProcessor 的父类。

for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					//处理
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}

然后又定义了一个集合,存放Spring自己定义的 BeanDefinitionRegistryPostProcessor。

//currentRegistryProcessors Spring内部自己实现这个接口的对象
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

通过类型的到自己定义的 BeanDefinitionRegistryPostProcessor,然后放到 currentRegistryProcessors 里面去。

我们可以知道这里只有一个类,也就是 ConfigurationClassPostProcessor ,前面一章我们讲到的创世纪的类,是在最开始的时候注册到 BeanDefinition 里面去的。

String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			
for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					//在这里注册了
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}

然后执行所有实现了 BeanDefinitionRegistryPostProcessor 的类。

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

我们点进去,他会执行 ConfigurationClassPostProcessor 这个类的 postProcessBeanDefinitionRegistry 这个方法。具体我们可以看一下思维导图。

在这里插入图片描述
首先会得到容器中已经注册的 BeanDefinition ,然后进行判断是否为以下三个条件。

String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
					ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
				}
			}
			//判断是不是5种类型类,添加到list中
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

1)isFullConfigurationClass

判断 BeanDefinition 的属性是不是 FULL。

2)isLiteConfigurationClass

判断 BeanDefinition 的属性是不是 LITE。

3)checkConfigurationClassCandidate

判断类是否有相关注解,并设置相关的属性 FULL 或 LITE,如果是 加了 @Configuration 注解就设置为 FULL,否则就看看看是不是以下四个注解,如果是就设置为 LITE,并放到集合中去。

static {
	candidateIndicators.add(Component.class.getName());
	candidateIndicators.add(ComponentScan.class.getName());
	candidateIndicators.add(Import.class.getName());
	candidateIndicators.add(ImportResource.class.getName());
}

//可能有多个配置类重复了
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
//alreadyParsed处理过就放到里面
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());

把符合条件的类放到 candidates 里面去重后,然后进行解析,解析代码如下,可以根据思维导图看。

parser.parse(candidates);

首先,比较重要的一点,就是把加了 @ComponentScans 注解的类拿出来,进行解析,解析后,会对加了 @ComponentScans 的类进行扫描,在这里,当吧所有的类进行扫描后,还会递归调用 checkConfigurationClassCandidate 方法判断一下是不是上面所提的5种类型。

//处理所有@ComSet<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			for (AnnotationAttributes componentScan : componentScans) {
				// The config class is annotated with @ComponentScan -> perform the scan immediately
				//扫描普通类,componentScan = com.javahly.xxx
				//扫描@Component
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						//解析,真正解析扫描包
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
				// Check the set of scanned definitions for any further config classes and parse recursively if needed
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}
					//检查扫描出的类是否有@Configuration并设置FULL和LITE
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

进入上面代码中的 parse 方法,我们可以看到,这里 new 了一个 ClassPathBeanDefinitionScanner 对包进行扫描,也就是实际扫描的是这里的ClassPathBeanDefinitionScanner ,而不是上一章的初始化时的 ClassPathBeanDefinitionScanner。

ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
      componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

然后调用 doScan 方法进行扫描包

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
   Assert.notEmpty(basePackages, "At least one base package must be specified");

   Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
   for (String basePackage : basePackages) {
      //扫描basePackage路径下的java文件
      //并把它转成BeanDefinition
      Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
      //拿出对象
      for (BeanDefinition candidate : candidates) {
         //解析scope属性
         ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
         candidate.setScope(scopeMetadata.getScopeName());
         String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
         if (candidate instanceof AbstractBeanDefinition) {
            //ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);(findCandidateComponents)
            //如果这个类是AbstractBeanDefinition的子类
            //则为他设置默认值,如lazy,init,destroy
            postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
         }
         //检查并且处理常用注解
         //这里的处理主要是把常用注解的值设置到AnnotatedBeanDefinition当中
         //当前这个类必须是AnnotatedBeanDefinition类型,也就是加了注解的类
         if (candidate instanceof AnnotatedBeanDefinition) {
            AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
         }
         if (checkCandidate(beanName, candidate)) {
            BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
            definitionHolder =
                  AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
            beanDefinitions.add(definitionHolder);
            //put到Map
            registerBeanDefinition(definitionHolder, this.registry);
         }
      }
   }
   return beanDefinitions;
}

最后,把扫描出来的类转化为 BeanDefinition 后,设置属性后,就放到了一个 Map 里面。

this.beanDefinitionMap.put(beanName, beanDefinition);

至此,普通的已经完成注册了,紧接着,就会处理加了 @Import 注解的类

processImports(configClass, sourceClass, getImports(sourceClass), true);
for (SourceClass candidate : importCandidates) {
   //是不是ImportSelector
   if (candidate.isAssignable(ImportSelector.class)) {
      // Candidate class is an ImportSelector -> delegate to it to determine imports
      //得到这个类
      Class<?> candidateClass = candidate.loadClass();
      //反射一个对象
      ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
      ParserStrategyUtils.invokeAwareMethods(
            selector, this.environment, this.resourceLoader, this.registry);
      if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
         this.deferredImportSelectors.add(
               new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
      } else {
         //回调
         String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
         Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
         //递归,Import的类本身有没有被Import
         //看返回的这个数组中的类是不是有@Import,有就处理,没有就放到Map里面
         //importSourceClasses 判断这个类是哪一种Import
         processImports(configClass, currentSourceClass, importSourceClasses, false);
      }
   }
   //是不是ImportBeanDefinitionRegistrar
   else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
      // Candidate class is an ImportBeanDefinitionRegistrar ->
      // delegate to it to register additional bean definitions
      Class<?> candidateClass = candidate.loadClass();
      ImportBeanDefinitionRegistrar registrar =
            BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
      ParserStrategyUtils.invokeAwareMethods(
            registrar, this.environment, this.resourceLoader, this.registry);
      configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
   } else {
      // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
      // process it as an @Configuration class
      //Import普通类
      //否则,加入importStack,调用processConfigurationClass处理
      this.importStack.registerImport(
            currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
      processConfigurationClass(candidate.asConfigClass(configClass));
   }
}

@import 的类型可能有三种,处理方式如下

ImportSelector 先把这个类放到 configurationClasses中 ,然后再注册

ImportBeanDefinitionRegistrar 放到 importBeanDefinitionRegistrars, 然后再注册

Import普通类 先把这个类放到 configurationClasses中,然后再注册

当扫描完成后,就会进行一些验证

parser.validate();

然后,就会调用以下方法注册,@Bean,Xml,Import 的 Bean,至此,所有的 Bean 就完成了注册。

this.reader.loadBeanDefinitions(configClasses);

至此,就解析完成了 实现 BeanDefinitionRegisterPostProcessor 的类,然后就会执行实现了 BeanFactoryPostProcessors 的类,也就是 BeanDefinitionRegisterPostProcessor 的父类 。

在这里插入图片描述

invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);

点进去,这是也是执行 ConfigurationClassPostProcessor 类的 postProcessBeanFactory 方法,里面执行这么一个方法,产生 CGLIB 代理。

enhanceConfigurationClasses(beanFactory);

得到所有的 BeanDefinition 看看有没有全注解类,也就是前面设置了 FULL 的类,加了 @Configuration 的类,如果有,就给这个类添加 CGLIB 动态代理,并添加属性 添加属性 &&beanFactory。

for (String beanName : beanFactory.getBeanDefinitionNames()) {
   BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
   //判断是否是一个全注解类
   //full和lite
   if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
      if (!(beanDef instanceof AbstractBeanDefinition)) {
         throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
               beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
      }
      else if (logger.isWarnEnabled() && beanFactory.containsSingleton(beanName)) {
         logger.warn("Cannot enhance @Configuration bean definition '" + beanName +
               "' since its singleton instance has been created too early. The typical cause " +
               "is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
               "return type: Consider declaring such methods as 'static'.");
      }
      configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
   }
}
if (configBeanDefs.isEmpty()) {
   // nothing to enhance -> return immediately
   return;
}
//不加@Configuration不会进这个方法
		ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
		for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
			AbstractBeanDefinition beanDef = entry.getValue();
			// If a @Configuration class gets proxied, always proxy the target class
			beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
			try {
				// Set enhanced subclass of the user-specified bean class
				Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
				if (configClass != null) {
					//完成cglib动态代理
					Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
					if (configClass != enhancedClass) {
						if (logger.isDebugEnabled()) {
							logger.debug(String.format("Replacing bean definition '%s' existing class '%s' with " +
									"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
						}
						beanDef.setBeanClass(enhancedClass);
					}
				}
			}
			catch (Throwable ex) {
				throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
			}
		}
private static final String BEAN_FACTORY_FIELD = "$$beanFactory";

为什么要添加动态代理,因为如果不加动态带来,当我们使用 @Bean 声明一个 Bean时,如果在一个@Bean方法里面调用另一个 @Bean 方法,就会产生两个实例,违背了单例原则,添加了代理类后,首先会进行判断,如果容器里面有这个 Bean,他就会调用 $$beanFactory 去直接 get,而不是又 new 一个。

三、结语

最后我们来总结一下比较重要的流程:

首先我们进入 refresh 方法里面,会调用 12 个方法(这里先讲前 5 个)
第一个 prepareRefresh 方法,这里进行一些准备工作;

第二个 obtainFreshBeanFactory 这里得到之前实例化的工厂;

第三个 prepareBeanFactory,这里对 beanFactory 进行一些简单的初始化工作;

第四个 postProcessBeanFactory 空方法;

第五个 invokeBeanFactoryPostProcessors,也是最重要的方法之一,在这个方法里面,会对实现了 BeanDefinitionRegistryPostProcessors 和 BeanFactoryPostProcessors 的类进行解析,其中包括我们自己定义的,也包括 Spring 内置的。

解析的顺序是先解析 BeanDefinitionRegistryPostProcessors ,再解析BeanFactoryPostProcessors。

这里会解析 Spring 内置的非常很重要的一个类,ConfigurationClassPostProcessor ,

首先会执行 postProcessBeanDefinitionRegistry 方法,在这里,会判断已经注册的类是不是加了@Configuration,如果是,就设置一个值为 FULL,不是就判断是不是其余四种,并设置为 LITE,并对加了 @ComponentScan 的类进行扫描,然后还会递归判断扫描出来的类是不是加了 @Configuration,以及还会判断扫描出来的类是普通类(加了 @Component的),还是加了@Import,的,然后进行相对应的注册。

然后会执行 BeanFactoryPostProcess 的 postProcessBeanFactory 方法,这里会判断有没有 FULL 类型的类,如果有,就添加 CGLIB 动态代理,作用是,当我们使用 @Bean 声明一个 Bean时,如果在一个@Bean方法里面调用另一个 @Bean 方法,就会产生两个实例,违背了单例原则,添加了代理类后,首先会进行判断,如果容器里面有这个 Bean,他就会调用 $$beanFactory 去直接 get,而不是又 new 一个。

为了更加直观的展现源码的调用过程,我绘制了一张思维导图!
为了更加直观的展现源码的调用过程,我绘制了一张思维导图!
为了更加直观的展现源码的调用过程,我绘制了一张思维导图!

Spring 思维导图

我的 Github:Github
CSDN: CSDN
个人网站: sirius 的博客
E-mail: [email protected]

推荐阅读
史上最全,最完美的 JAVA 技术体系思维导图总结,没有之一!

发布了81 篇原创文章 · 获赞 373 · 访问量 27万+

猜你喜欢

转载自blog.csdn.net/Sirius_hly/article/details/98507799
今日推荐