【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的创建(持续更新中~~~)

相关推荐
P.H. Infinity3 分钟前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天7 分钟前
java的threadlocal为何内存泄漏
java
caridle18 分钟前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
^velpro^23 分钟前
数据库连接池的创建
java·开发语言·数据库
苹果醋327 分钟前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx
秋の花32 分钟前
【JAVA基础】Java集合基础
java·开发语言·windows
小松学前端34 分钟前
第六章 7.0 LinkList
java·开发语言·网络
Wx-bishekaifayuan41 分钟前
django电商易购系统-计算机设计毕业源码61059
java·spring boot·spring·spring cloud·django·sqlite·guava
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
全栈开发圈1 小时前
新书速览|Java网络爬虫精解与实践
java·开发语言·爬虫