【Spring生命周期核心底层源码之剖析】

文章目录

一、Spring生命周期核心底层源码剖析---扫描

1.1、Spring底层扫描机制doScan方法源码剖析

其源代码如下:

java 复制代码
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) {
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			//遍历其获取到的BeanDefinition对象
			for (BeanDefinition candidate : candidates) {
				//为其BeanDefinition对象进行属性赋值,例如scope,beanName等
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				//判断当前的bean是否已经在Spring容器中存在,不存在返回True,将对象需封装为BeanDefinitionHolder对象,注册到BeanDefinitionMap中,若存在,会判断是否为同样类型,若是,返回false,不重新注入,若存在且不是同样类型,抛出异常
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					//将BeanDefinition加入BeanDefinitionMap中
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

1、其主要是通过传入的包路径进行资源加载,加载时方法为上诉代码的for循环下的第一行代码的findCandidateComponents()方法,可以详细看此方法,是如何加载资源的,其方法代码如下(具体说明以及解析过程可参考注释):

java 复制代码
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
		//此处主要是判断项目是否配置了相关的bean文件,若有,就不需要再逐个类进行扫描+判断是否为Bean
		if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
			return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
		}
		//大部分的业务都会走如下方法
		else {
			return scanCandidateComponents(basePackage);
		}
	}
	
//scanCandidateComponents方法具体实现为
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
		Set<BeanDefinition> candidates = new LinkedHashSet<>();
		try {
			//1、资源路径组装解析
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
			//2、利用类元数据读取器读取器路径下包含的资源数据
			Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
			boolean traceEnabled = logger.isTraceEnabled();
			boolean debugEnabled = logger.isDebugEnabled();
			//3、遍历类元数据读取器获取到的资源数据(class资源文件数据)
			for (Resource resource : resources) {
				if (traceEnabled) {
					logger.trace("Scanning " + resource);
				}
				try {
					//4、获取当前类元数据(calss)具体资源信息
					MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
					//5、判断当前的类(class)上包含的是否包含排除注解excludeFilters以及非排除注解includeFilters,以及是否包含相关的条件注解Conditional
					if (isCandidateComponent(metadataReader)) {
						//6、创建一个BeanDefinition对象,用于封装其类特征信息,例如:beanClass、scope、lazyInit等属性
						ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
						//7、将类资源数据加入到BeanDefinition中
						sbd.setSource(resource);
						//8、判断当前的类资源是否是独立的(例如是否是内部类等),除此歪,需要判断其是否为接口或者抽象类,如果是抽象类,那类中必须有被Lookup注解的方法,否则不会被当做bean
						if (isCandidateComponent(sbd)) {
							if (debugEnabled) {
								logger.debug("Identified candidate component class: " + resource);
							}
							//9、将封装好的BeanDefinition对象加入到返回的集合Set中
							candidates.add(sbd);
						}
						else {
							if (debugEnabled) {
								logger.debug("Ignored because not a concrete top-level class: " + resource);
							}
						}
					}
					else {
						if (traceEnabled) {
							logger.trace("Ignored because not matching any filter: " + resource);
						}
					}
				}
				catch (FileNotFoundException ex) {
					if (traceEnabled) {
						logger.trace("Ignored non-readable " + resource + ": " + ex.getMessage());
					}
				}
				catch (Throwable ex) {
					throw new BeanDefinitionStoreException(
							"Failed to read candidate component class: " + resource, ex);
				}
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
		}
		return candidates;
	}

扫描完毕后,那接下来就是创建非懒加载的Bean,示例代码如下:

java 复制代码
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.refresh();

refresh方法的源代码中的

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

finishBeanFactoryInitialization(beanFactory);

即为初始化非懒加载的单例bean,那就先来探索其实现的过程是如何的

java 复制代码
	/**
	 * Finish the initialization of this context's bean factory,
	 * initializing all remaining singleton beans.
	 */
	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}

		// Register a default embedded value resolver if no BeanFactoryPostProcessor
		// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// Stop using the temporary ClassLoader for type matching.
		beanFactory.setTempClassLoader(null);

		// Allow for caching all bean definition metadata, not expecting further changes.
		beanFactory.freezeConfiguration();

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

其方法preInstantiateSingletons即为初始化非懒加载的bean,继续点进方法(执行过程看参考注释信息):

java 复制代码
@Override
	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.
		//1、获取其class名称形式为:com.xx.xx.Xxxx.class
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		//2、遍历获取的资源数据
		for (String beanName : beanNames) {
			//3、合并其BeanDefinition,存在父子关系的Bean,需要合并为一个BeanDefinition,底层会结合BeanDefinition中的parentName与是否为RootBeanDefinition,判断其是否需要多个BeanDefinition合并
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//4、判断当前的Bean是否为非懒加载的单例bean,并且当前的BeanDefinition为非抽象的
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				//5、判断其bean是否为factoryBean
				if (isFactoryBean(beanName)) {
					//6、在beanName基础上加&符号,获取单例池中的对象
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					//7、判断其拿出来的对象是否为factoryBean
					if (bean instanceof FactoryBean) {
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						//8、如果是当前对象为factoryBean且实现了SmartFactoryBean接口,此时需要执行isEagerInit方法
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						//9、上一步执行的结果若为true,创建其getObject中的方法,并将其加入到缓存的Map中
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				//10、如果不是factoryBean,直接创建单例bean
				else {
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		//创建所有的非懒加载的单例bean后,此处的逻辑为判断当前的单例对象是否实现了SmartInitializingSingleton接口,若实现了,这里需要调用其对象中的afterSingletonsInstantiated方法执行相关业务逻辑代码
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
						.tag("beanName", beanName);
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
				smartInitialize.end();
			}
		}
	}

二、Spring生命周期核心底层源码剖析---bean的创建(持续更新中~~~)

相关推荐
重生之我要进大厂9 分钟前
LeetCode 876
java·开发语言·数据结构·算法·leetcode
_祝你今天愉快12 分钟前
技术成神之路:设计模式(十四)享元模式
java·设计模式
小筱在线1 小时前
SpringCloud微服务实现服务熔断的实践指南
java·spring cloud·微服务
luoluoal1 小时前
java项目之基于Spring Boot智能无人仓库管理源码(springboot+vue)
java·vue.js·spring boot
ChinaRainbowSea1 小时前
十三,Spring Boot 中注入 Servlet,Filter,Listener
java·spring boot·spring·servlet·web
小游鱼KF1 小时前
Spring学习前置知识
java·学习·spring
扎克begod1 小时前
JAVA并发编程系列(9)CyclicBarrier循环屏障原理分析
java·开发语言·python
青灯文案11 小时前
SpringBoot 项目统一 API 响应结果封装示例
java·spring boot·后端
我就是程序猿1 小时前
tomcat的配置
java·tomcat
阳光阿盖尔1 小时前
EasyExcel的基本使用——Java导入Excel数据
java·开发语言·excel