前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >spring源码篇(三)bean的生命周期

spring源码篇(三)bean的生命周期

作者头像
用针戳左手中指指头
修改2023-10-24 18:47:09
7860
修改2023-10-24 18:47:09
举报
文章被收录于专栏:学习计划

前言

Bean的生命周期在spring中是很重要的一个概念,bean的生成和spring密不可分,想搞懂spring,先要了解bean的生命周期。

最核心的问题就是,了解bean的生命周期。

Bean的生命周期

spring的特点是IOC(控制反转),而启动spring就是为创建bean对象做准备,所以我们先了解bean是怎么创建的,需要什么。

下面这张图描述的就是bean完整的生命周期。(网图)

bean的生命周期从包扫描后开始。

生成BeanDefinition

扫描包路径,获取class文件,然后遍历生成BeanDefinition,在ClassPathScanningCandidateComponentProvider#scanCandidateComponents

代码语言:javascript
复制
/**
	 * 扫描候选的components
	 * @param basePackage
	 * @return
	 */
	private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
		// 扫描类,得到BeanDefinition
		Set<BeanDefinition> candidates = new LinkedHashSet<>();
		try {
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
			// 读取包路径下的资源文件
			Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
			boolean traceEnabled = logger.isTraceEnabled();
			boolean debugEnabled = logger.isDebugEnabled();
			for (Resource resource : resources) {
				// 省略。。。
				if (resource.isReadable()) {
					try {
						// MetadataReader包含了对应class的元信息以及注解元信息, MetadataReader
						MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
						// 判断一个类是不是Component
						if (isCandidateComponent(metadataReader)) {
							// 通过扫描@Component得到的BeanDefinition为ScannedGenericBeanDefinition
							ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
							sbd.setResource(resource);
							sbd.setSource(resource);
							// 再进一步验证是不是备选的Component
							if (isCandidateComponent(sbd)) {
								// 省略。。。
								candidates.add(sbd);
							}
							else {
								// 省略。。。
							}
						}
						else {
							// 省略。。。
						}
					}
					catch (Throwable ex) {
						// 抛异常 省略。。。
					}
				}
				else {
					// 省略。。。
				}
			}
		}
		catch (IOException ex) {
			// 抛异常 省略。。。
		}
		return candidates;
	}

上述代码中,从resource获取到了MetadataReader,它相当于是class文件解析后的信息。

MetadataReader对象有三个功能:

  • 获取对应resource资源;
  • 获取resource对应的class的元数据信息,包括名称、是否是注解、是否抽象等,具体可以查看类ClassMetadata的接口;
  • 获取resource对应的class上的注解信息,如当前类上有的注解,被注解标注的方法等;

这里生成的ScannedGenericBeanDefinition中有一属性beanClass,在这里存的是字符串,就是类全名,spring中使用ASM技术解析class文件,会得到class的所有信息,但不会加载类,所有在这里的beanClass保存了类名,beanClass的类型为Object,是因为,它可以存储不止字符串一种类型,也可以存储class类型,在用到这个类时才会加载,那么就会存class对象。

合并beanDefinition

在有了beanDefinition之后,会进行一次beanDefinition合并,其意义在于如果一个bean类继承了父类,而父类又设置了一些注解(或者是xml配置文件中的bean标签上设置了属性)或是属性,那么子类会继承这些属性,比如,父类有配置scope为原型,那么继承的子类没有重写,那么getBean得到也是一个原型,其原理就是因为做了合并,要注意的是,这个合并方式是基于父类进行合并的。

如下:

这里以xml方式进行演示,因为注解方式的有些不同,在生成beanDefinition时就默认设置了单例属性,xml这边呢,在合并beanDefinition之前没有就是没有,注解componentScan会默认设置的单例属性,但是设置是在合并方法里,下面代码可以看到。

代码语言:javascript
复制
	<bean id="parentService" class="com.lry.service.ParentService" scope="prototype"/>
	<bean id="userService" class="com.lry.service.UserService" parent="parentService"/>

如下图,在走到合并beanDefinition方法的时候,userService的scope还是空,而父类parentService是prototype。

g)

在走过合并方法后,得到的userService的scope已经变了。

结果可以看到,userService继承了parentService,而parentService设置里scope为原型类型,userService也是原型类型。

再来看看源码里是怎样的DefaultListableBeanFactory.preInstantiateSingletons()方法

代码语言:javascript
复制
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}
		// 在spring启动时,就将bean的名字保存起来了
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
		// 循环bd,实例化非懒加载单例bean
		for (String beanName : beanNames) {
			// 对beanDefinition进行合并,基于合并后的BeanDefinition去创建bean
			// 合并是子类合并到父类,才有完整的定义信息
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			// 非抽象,单例,非懒加载
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				// 判断是不是一个SmartFactoryBean
				if (isFactoryBean(beanName)) {
					//  如果是一个FactoryBean,那么需要加上前缀
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						// eager:急切的意思,立马初始化
						// smartFactoryBean 有一个接口,isEagerInit,是否立即初始化
						// System.getSecurityManager() 是安全管理器,不用管
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							// 是立即初始化,就根据beanName去生成FactoryBean中所生成的Bean对象
							getBean(beanName);
						}
					}
				}
				else {
					// 根据beanName去创建bean
					getBean(beanName);
				}
			}
		}

		// 创建完所有的单例bean之后,判断某个单例bean是不是SmartInitializingSingleton,如果是执行afterSingletonsInstantiated()方法
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

进入getMergedLocalBeanDefinition方法,一开始,mergedBeanDefinitions是空的,都是在执行这个方法后添加的。

代码语言:javascript
复制
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
		// 从已合并的容器中取
		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
		if (mbd != null && !mbd.stale) {
			return mbd;
		}
		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
	}
代码语言:javascript
复制
protected RootBeanDefinition getMergedBeanDefinition(
			String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
			throws BeanDefinitionStoreException {
		// bd 可以说是我们要拿的bean的beanDefinition;
		synchronized (this.mergedBeanDefinitions) {
			RootBeanDefinition mbd = null;
			RootBeanDefinition previous = null;

			if (containingBd == null) {
				mbd = this.mergedBeanDefinitions.get(beanName);
			}
			// 取不到合并的beanDefinition
			if (mbd == null || mbd.stale) {
				previous = mbd;
				// 如果bd的父bd为空,说明它是个rootBeanDefinition
				if (bd.getParentName() == null) {
					// RootBeanDefinition没有父BeanDefinition
					if (bd instanceof RootBeanDefinition) {
						// 如果bd已经是rootBeanDefinition,就克隆一份返回
						mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
					}
					else {
						// 还不是rootBeanDefinition,就生成一个
						mbd = new RootBeanDefinition(bd);
					}
				}
				else {
					// bd存在父类
					BeanDefinition pbd;
					try {
						// 父bd的beanName
						String parentBeanName = transformedBeanName(bd.getParentName());
						if (!beanName.equals(parentBeanName)) {
							// 递归调用,因为父bean 还可能有父bean,所以再次调用合并得到父的beanDefinition
							pbd = getMergedBeanDefinition(parentBeanName);
						}
						else {
							// 一般不会走
							// 到父容器中找对应的bean,然后进行合并,合并也发生在父容器中
							BeanFactory parent = getParentBeanFactory();
							if (parent instanceof ConfigurableBeanFactory) {
								pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
							}
							else {
								// 抛异常 省略。。。
							}
						}
					}
					catch (NoSuchBeanDefinitionException ex) {
						throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
								"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
					}
					// pbd表示父BeanDefinition, bd表示本BeanDefinition
					mbd = new RootBeanDefinition(pbd);
					// 基于mbd,将bd属性设置进去,就是合并,这里可以说是覆盖
					mbd.overrideFrom(bd);
				}

				// 如果没有设置scope,就设置默认为singleton
				if (!StringUtils.hasLength(mbd.getScope())) {
					mbd.setScope(SCOPE_SINGLETON);
				}

				// 如果某个<bean/>内包含了一个内部<bean/>,containingBd表示外部bean, mbd表示内部bean
				// 外部bean如果不是单例bean,内部bean是单例的,那么则把内部bean的scope设置为和外部bean的scope一样的
				if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
					mbd.setScope(containingBd.getScope());
				}

				// 将合并后的bd放入到mergedBeanDefinitions这个map中
				// 之后还是可能被清空的,因为bd可能被修改
				if (containingBd == null && isCacheBeanMetadata()) {
					this.mergedBeanDefinitions.put(beanName, mbd);
				}
			}
			if (previous != null) {
				copyRelevantMergedBeanDefinitionCaches(previous, mbd);
			}
			return mbd;
		}
	}

这里需要讲一下这个beanName获取的方式,因为上面有这样的方法。

传进去beanName可以有3种:

  1. beanName即bean的名称,也可以说是实际名称
  2. factoryBean 的名称,而要得到factoryBean的name需要转义,不然获取的就是它生成的bean,就和第一点的一样。如&userService,在beanName前面有一个前缀。
  3. 别名;是我们为这些bean设置的名称
代码语言:javascript
复制
protected String transformedBeanName(String name) {  
		return canonicalName(BeanFactoryUtils.transformedBeanName(name));
	}

BeanFactoryUtils.transformedBeanName(name)方法是为了拿到实际的beanName,将factoryBean之前的&去除。

代码语言:javascript
复制
public static String transformedBeanName(String name) {
		Assert.notNull(name, "'name' must not be null");
		// 如果beanName没有以&开头,则直接返回
		if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {   
			return name;
		}
		// 如果beanName以&开头,截取&后的beanName,并且把截取前后的name存在transformedBeanNameCache中
		return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
			do {
				beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
			}
			while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
			return beanName;
		});
	}

canonicalName方法这里是获取实际的beanName,因为在spring中各种处理都是围绕着实际的name进行的。

代码语言:javascript
复制
public String canonicalName(String name) {
		String canonicalName = name;
		String resolvedName;
		do {
            // 从aliasMap中获取到对应的实际名称,在aliasMap中通过别名,保存着实际的类名
			resolvedName = this.aliasMap.get(canonicalName);
			if (resolvedName != null) {
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		return canonicalName;
	}

加载类

在合并完beanDefinition后,又回到了DefaultListableBeanFactory.preInstantiateSingletons()方法

代码语言:javascript
复制
public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}
		// 在spring启动时,就将bean的名字保存起来了
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
		// 循环bd,实例化非懒加载单例bean
		for (String beanName : beanNames) {
			// 对beanDefinition进行合并,基于合并后的BeanDefinition去创建bean
			// 合并是子类合并到父类,才有完整的定义信息
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			// 非抽象,单例,非懒加载
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				// 判断是不是一个SmartFactoryBean
				// 省略。。。
                if(){}
				else {
					// 根据beanName去创建bean
					getBean(beanName);
				}
			}
		}

		// 创建完所有的单例bean之后,判断某个单例bean是不是SmartInitializingSingleton,如果是执行afterSin
    // 省略。。。
	}

在方法下面有一个getBean的方法,进入getBean(beanName);方法,在doGetBean方法里你会找到createBean这个方法,类就是在createBean中被加载的。

下面看doGetBean,代码有点长,分段慢慢看,加载类是在创建bean的时候创建的,但是这里还不是底层创建bean的地方。

代码语言:javascript
复制
	// 对beanName进行转换 name如果是"&lubanFactoryBean",那么beanName就是"lubanFactoryBean"
		final String beanName = transformedBeanName(name);
		Object bean;
		// 从单例池中取单例bean
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					// 省略。。
			}
			// 判断sharedInstance是不是FactoryBean,如果是FactoryBean,那么真正需要拿到的是getObject方法所返回的对象
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

上面这段是从容器中获取bean,或者是从factoryBean获取Object;

当从单例池中获取不到bean时,先判断是否在创建中(创建bean是都会先添加记号),然后如果是还没创建,那么再从父容器中找找看,找到旧直接返回。

代码语言:javascript
复制
// 原型bean正在创建中
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			// 当前BeanFactory中不存beanName对象的BeanDefinition,那么则从ParentBeanFactory中去获取
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// 这里意思就是,当前容器拿不到,那么让父容器去拿,有可能在父容器就有
				// Not found -> check parent.
				// 原始的beanName
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

上面两步中,都没拿到bean,那么就需要创建了,在创建之前,要添加一个记号,表示它要创建这个bean了,其他人等着。

代码语言:javascript
复制
	// 走到这一步,就是还没拿到bean,所以要创建Bean
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

这里又获取了一次beanDefinition,因为在这个过程中,beanDefinition很可能被修改,所以要一直保持最新的。

然后查看这次要创建的bean是否有依赖了其他bean,有依赖的需要先创建依赖的bean,所以这里又调用了一次getBean,实现了递归,因为不能保证依赖的bean,是不是又依赖了另一个bean。

代码语言:javascript
复制
// 得到合并后的BeanDefinition;获取最新的定义
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);
				// 加载DependsOn的bean(依赖的bean)
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						// 判断beanName是不是也被dep依赖了,如果是,就是相互依赖
						if (isDependent(beanName, dep)) {
							// 抛异常 省略。。。
						}
						// 存在在两个map中
						// 1. dependentBeanMap,key为dep, value是一个LinkedHashSet,表示dep被哪些bean依赖了
						// 2. dependenciesForBeanMap,key为beanName,value是一个LinkedHashSet,表示beanName依赖了哪些bean
						registerDependentBean(dep, beanName);
						try {
							// 先去拿依赖的bean,然后又是递归,再查找依赖的bean的依赖的bean
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							// 抛异常 省略。。。
						}
					}
				}

依赖检验通过后,这里是根据bean的作用域去创建bean,如果是singleton的话,调用createBean方法生成bean,然后添加到单例池总。

而如果是原型bean的话,就会直接调用createBean生成。

代码语言:javascript
复制
// 根据Scope去创建bean
				if (mbd.isSingleton()) {
					// 获取单例bean,如果获取不到则创建一个bean,并且放入单例池中
					// 这里使用了函数式接口
					sharedInstance = getSingleton(beanName, () -> {
						try {
								return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// 抛异常 省略。。。
						}
					});
					// sharedInstance可能是一个FactoryBean,所以需要单独再去factoryBeanObjectCache中去获取对应的对象
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						// 记录在创建的bean
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						// 创建完后,就移除
						afterPrototypeCreation(beanName);
					}
					// 因为是单例的,创建出来后,就没添加单例池
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

而如果都不是singleton和prototype,那么就是sessionScope、RequestScope这些的作用域,

代码语言:javascript
复制
else {
    // 这里的scope是sessionScope和RequestScope,
    String scopeName = mbd.getScope();
    final Scope scope = this.scopes.get(scopeName);
    if (scope == null) {
        // 抛异常 省略。。。
    }
    try {
        // 这里调用的是`AbstractRequestAttributesScope`里的get方法
        Object scopedInstance = scope.get(beanName, () -> {
            // 记录在创建的bean
            beforePrototypeCreation(beanName);
            try {
                return createBean(beanName, mbd, args);
            }
            finally {
                // 移除记录
                afterPrototypeCreation(beanName);
            }
        });
        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    }
    catch (IllegalStateException ex) {
        // 抛异常 省略。。。
    }
}

而scope.get方法是AbstractRequestAttributesScope里的方法,resquestScope 和 sessionScope 都继承这个对象,也都调用这一个方法,在attributes.getAttributeattributes.setAttribute里它都有去判断是哪一个scope。

看一下这个scope.get方法:

代码语言:javascript
复制
public Object get(String name, ObjectFactory<?> objectFactory) {
		RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
		// 从属性中获取
		Object scopedObject = attributes.getAttribute(name, getScope());
		if (scopedObject == null) {
			// 拿不到就是没有,那么从函数式接口中获取,就是在外层方法我们返回的值
			scopedObject = objectFactory.getObject();
			// 拿到之后设置到属性中
			// request -> request.setAttribute(name, value);
			// session -> session.setAttribute(name, value);
			attributes.setAttribute(name, scopedObject, getScope());
			// 它这里再次进行了取值,注释上说校验,我觉得它是以从会话或是请求对象中取的为准,
			// 而再次取值还是没取到,它也没办法,还是得继续处理,感觉作用不大
			Object retrievedObject = attributes.getAttribute(name, getScope());
			if (retrievedObject != null) {
				scopedObject = retrievedObject;
			}
		}
		return scopedObject;
	}

最后就是对生成的bean进行类型转化,就是会判断是否是我们需要的 bean,这里的类型转化器,是获取的自定义的,也就是可以获取我们自定义的转化器。

代码语言:javascript
复制
	// 根据beanName获取到的bean的类型是否和requiredType匹配,如果不配则进行类型转化
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isTraceEnabled()) {
					logger.trace("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}

上面在创建单例和原型bean(singleton、prototype)时,都调用了createBean方法,这里再详细看一下

代码语言:javascript
复制
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
// 省略。。。
		RootBeanDefinition mbdToUse = mbd;

		// 拿到bean Class
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			// 这里是没有beanClass,这里的beanClass指的是类对象class
			// 之前在得到beanDefinition时,存的是类全名(字符串)
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		try {
			// 对通过XML定义的bean中的look-up方法进行预处理
			// 对于@Lookup注解标注的方法不在这里进行处理,@AutowiredAnnotationBeanPostProcessor会处理@Lookup注解
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			// 抛异常 省略。。。
		}

		try {
			// 1、实例化前 null
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);  // 对象
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			// 抛异常 省略。。。
		}

		try {
			// 创建bean   Spring自带的创建bean的方法
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			// 抛异常 省略。。。
		}
	}

上面代码中第一行是Class<?> resolvedClass = resolveBeanClass(mbd, beanName);加载类就是在这里处进行的,进入里面是下面这段,大概意思是如果beanClass的类型是class,就直接返回,不是就根据类名加载。

代码语言:javascript
复制
// 直接返回beanClass
if (mbd.hasBeanClass()) {
   return mbd.getBeanClass();
}
if (System.getSecurityManager() != null) {
   return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
      doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
   // 加载BeanDefinition中beanClass中所指定的类名对应的类
   return doResolveBeanClass(mbd, typesToMatch);
}

实例化前

接着看createBean方法,里面有这个方法resolveBeforeInstantiation

代码语言:javascript
复制
// 1、实例化前 null
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);  // 对象
if (bean != null) {
    return bean;
}
代码语言:javascript
复制
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		// beforeInstantiationResolved为null或true
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// isSynthetic 是由编译器引入字段、方法、类或其他结构,复杂东西,忽略
			// hasInstantiationAwareBeanPostProcessors 是否有实例化bean的后置处理器
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				// 确定bean的类型
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					// 实例化前
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
                        // 在bean返回之前,做一些后置的初始化操作进行干涉
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

这里执行实例化bean的处理器,有两个方法applyBeanPostProcessorsBeforeInstantiationapplyBeanPostProcessorsAfterInitialization,他们都是接口InstantiationAwareBeanPostProcessor,它提供了一些方法,可以对bean进行干涉,并且每一个bean都会走这个逻辑;在看上面代码中的这段,是调用了我们自己的后置处理器返回了一个bean,然后返回,这里是bean的生命周期都结束了,因为bean的生成过程由我们自己去控制了,再返回来的时候已经是一个完整的bean了,所以这里要做到bean初始化后的操作,就需要在执行bean的后置初始化操作,所以才有的 if 判断中的内容。

代码语言:javascript
复制
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
    // 在bean返回之前,做一些后置的初始化操作进行干涉
    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}

进入applyBeanPostProcessorsBeforeInstantiation,看getBeanPostProcessors方法,它把所有的postProcess都取出来了。

代码语言:javascript
复制
	protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

关于后置处理器我举个例子:

实现InstantiationAwareBeanPostProcessor,然后通过方法返回我定义的一个实例,那么之后创建的bean就会如我所愿已经设置好了自定义User。那么之前也说了,每个bean的创建都会遍历postProcess,所有这里我加了if判断。

代码语言:javascript
复制
@Component
public class CustomPostProcessor implements InstantiationAwareBeanPostProcessor {
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		if (beanClass.equals(UserService.class)) {
			User user = new User();
			user.setName("before post processor");
			UserService userService = new UserService();
			userService.setUser(user);
			return userService;
		}
		return null;
	}
}

下面这段,这里要注意下就是执行applyBeanPostProcessorsAfterInitialization方法(实例化后后置处理器),这个处理器方法默认是返回bean的,如果其中一个处理器返回了null,那么循环就结束了,之后的处理器就不会执行。

代码语言:javascript
复制
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			// 这里返回null就直接返回了
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

推断构造方法

这篇博客大佬有详细分析:https://blog.csdn.net/xjk201/article/details/109996292

再回到createBean方法,resolveBeforeInstantiation实例化前的操作完了之后,接着执行doCreateBean;如果在resolveBeforeInstantiation中得到bean了,那么就不会走doCreateBean方法了。

代码语言:javascript
复制
try {
			// 1、实例化前 null
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);  // 对象
    if (bean != null) {
        return bean;
    }
}
catch (Throwable ex) {
    // 省略。。。
}

try {
    // 创建bean   Spring自带的创建bean的方法
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    if (logger.isTraceEnabled()) {
        logger.trace("Finished creating instance of bean '" + beanName + "'");
    }
    return beanInstance;
}

在前面resolveBeforeInstantiation没有得到bean,这里是进入doCreateBean方法去创建bean。然后找到createBeanInstance方法,就下面这句

代码语言:javascript
复制
// 2、实例化
		if (instanceWrapper == null) {
			// 创建bean实例  new USerSerive()
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}

进入createBeanInstance方法,推断构造器的主要逻辑从这里开始,下面代码中,第一点是获取class,第2,第3点都是实例化bean对象,但这两步并不是我们要看的方法,这两步就相当于我们手动实例化一样,因为是经由我们的方法去实例化的,已经跳过了推断构造这个过程了。所以我们要从第4点开始

代码语言:javascript
复制
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// 创建一个bean实例(返回一个原始对象)

		// Make sure bean class is actually resolved at this point.
		// 1. 得到bean的class,并验证class的访问权限是不是public
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

		// 2. 这是Spring提供给开发者的扩展点
		// 如果我们要自己来实现创建对象的过程, 那么就可以提供一个Supplier的实现类,
		// 当一个BeanDefinition中存在一个Supplier实现类的时候, Spring就利用这个类的get方法来获取实例,
		// 而不再走Spring创建对象的逻辑
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		// 3.通过factoryMethod实例化这个bean
		// factorMethod这个名称在xml中还是比较常见的, 即通过工厂方法来创建bean对象
		// 如果一个bean对象是由@Bean注解创建的, 那么该对象就会走instantiateUsingFactoryMethod方法来创建的
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		boolean resolved = false;
		boolean autowireNecessary = false;
		// 4. 如果在创建bean时没有手动指定构造方法的参数,那么则看当前BeanDefinition是不是已经确定了要使用的构造方法和构造方法参数
		// 注意:如果没有手动指定参数,那么就肯定时自动推断出来的,所以一旦发现当前BeanDefinition中已经确定了要使用的构造方法和构造方法参数,
		// 那么就要使用autowireConstructor()方法来构造一个bean对象
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				// 该BeanDefinition是否已经决定了要使用的构造方法或工厂方法
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					// 该BeanDefinition是否已经决定了要使用的构造方法参数
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {
			// resolved为true,表示当前bean的构造方法已经确定出来了
			// autowireNecessary表示
			if (autowireNecessary) {
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				// 如果构造方法已经确定了,但是没有确定构造方法参数,那就表示没有构造方法参数,用无参的构造方法来实例化bean
				return instantiateBean(beanName, mbd);
			}
		}

		// Candidate constructors for autowiring?
    // 获取@Autowire的注解的构造器
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

		// 通过BeanPostProcessor找出了构造方法
		// 或者BeanDefinition的autowire属性为AUTOWIRE_CONSTRUCTOR
		// 或者BeanDefinition中指定了构造方法参数值
		// 或者在getBean()时指定了args
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			// 进行构造方法推断并实例化
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// Preferred constructors for default construction?
		// 没啥用
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		// No special handling: simply use no-arg constructor.
		// 用无参的构造方法来实例化bean
		return instantiateBean(beanName, mbd);
	}

实例化

上面的代码的最后,在createBeanInstance方法后面,通过反射生成得到实例,所有加载类的作用就是反射创建bean的实例。

代码语言:javascript
复制
return instantiateBean(beanName, mbd);

BeanDefinition后置处理器处理

再返回到doCreateBean方法,在上面实例化得到对象后,有一个后置处理器,这个处理器是为了做依赖注入(填充属性)做准备,它在这个地方,的作用是查找注入点。

代码语言:javascript
复制
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
代码语言:javascript
复制
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof MergedBeanDefinitionPostProcessor) {
				MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
				bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
			}
		}
	}

在这步,我们也可以自定义一些处理器,对实例化好的bean做一些处理,在这里改beanClass是无效的,以为你bean已经实例化好了。下面是一个自定义的例子:

代码语言:javascript
复制
@Component
public class CustomMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {

	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		Class<?> beanClass = beanDefinition.getBeanClass();
		if (beanClass.equals(UserService.class)) {
			MenuService menuService = new MenuService();
			menuService.setName("MergedBeanDefinitionPostProcessor。。。");
			beanDefinition.getPropertyValues().add("menuService", menuService);
		}
	}
}

填充属性

这里基本就是依赖注入的东西了。之后会详细一篇;

在这里就是查找注入点,然后对需要注入的属性进行填充,比如我们xml里配置了注入类型,或是使用了@Autowired等这些,就是要注入的。

代码语言:javascript
复制
// 3、填充属性 @Autowired
populateBean(beanName, mbd, instanceWrapper); 

执行aware

进入initializeBean方法

代码语言:javascript
复制
exposedObject = initializeBean(beanName, exposedObject, mbd);
代码语言:javascript
复制
// 4.1、执行Aware
invokeAwareMethods(beanName, bean);
代码语言:javascript
复制
if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}

aware接口的作用就是能够获取的容器服务。

初始化前

紧接着

代码语言:javascript
复制
// 4.2、初始化前
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
代码语言:javascript
复制
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

它里通过后置处理器得到对象current,这里的处理和之前看到不一样,这里是只要一个处理器返回null,就不会再执行后面的处理器了。

初始化

代码语言:javascript
复制
// 4.3、初始化
invokeInitMethods(beanName, wrappedBean, mbd);
代码语言:javascript
复制
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

		boolean isInitializingBean = (bean instanceof InitializingBean);
    // 第一:执行isInitializingBean的afterPropertiesSet
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
			if (logger.isTraceEnabled()) {
				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			}
			if (System.getSecurityManager() != null) {
				try {
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				((InitializingBean) bean).afterPropertiesSet();
			}
		}
// 第二:执行InitMethod方法
		if (mbd != null && bean.getClass() != NullBean.class) {
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				invokeCustomInitMethod(beanName, bean, mbd);   // init-method=""
			}
		}
	}

这边先是执行了InitializingBeanafterPropertiesSet方法,然后又执行initMethod方法,这两个区别是afterPropertiesSet直接调用方法执行,而initMethod是反射执行的,而且支持private的访问类型。

初始化后

紧接着后面又有处理器,aop的就是在这里处理的,同样是返回null就会结束处理器链调用。

代码语言:javascript
复制
// 4.4、初始化后
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

Bean 的销毁

  1. 容器关闭
  2. 发布ContextClosedEvent事件
  3. 调用LifecycleProcessor的onClose方法
  4. 销毁单例bean
代码语言:javascript
复制
	protected void doClose() {
		// Check whether an actual close attempt is necessary...
		if (this.active.get() && this.closed.compareAndSet(false, true)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Closing " + this);
			}

			LiveBeansView.unregisterApplicationContext(this);

			try {
				// Publish shutdown event.
				publishEvent(new ContextClosedEvent(this));
			}
			catch (Throwable ex) {
				logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
			}

			// Stop all Lifecycle beans, to avoid delays during individual destruction.
			if (this.lifecycleProcessor != null) {
				try {
					this.lifecycleProcessor.onClose();
				}
				catch (Throwable ex) {
					logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
				}
			}

			// Destroy all cached singletons in the context's BeanFactory.
			destroyBeans();

			// Close the state of this context itself.
			closeBeanFactory();

			// Let subclasses do some final clean-up if they wish...
			onClose();

			// Reset local application listeners to pre-refresh state.
			if (this.earlyApplicationListeners != null) {
				this.applicationListeners.clear();
				this.applicationListeners.addAll(this.earlyApplicationListeners);
			}

			// Switch to inactive.
			this.active.set(false);
		}
	}

总结

我用思维导图把上面的流程捋了一遍。

深色的就是上面的各个步骤,偏绿色,和绿色的是后置处理器的部分,一共6次调用,就是说我们有6次机会修改bean,还每一算上填充属性里的后置处理器。

深蓝色和蓝绿色的是上面的生命周期阶段;

绿色字体和蓝绿色的是后置处理器处理的调用;

蓝色字体的是可以自定义实现的bean初始化的地方;

那么还是围绕问题回顾一下

为什么要有beanDefinition

spring在启动后扫描,会得到beanDefinition,然后在实例化bean时,通过getBean获取一个bean,要判断这个bean是否懒加载,是否单例等等,那么这时候就不能再去解析了,因为在启动时就扫描解析过一次了,所以在第一次扫描解析会把bean的各种信息保存用来创建bean,这就是beanDefinition的作用

为什么要用asm技术,不直接接着类

首先asm解析技术的效率高,在第一次扫描后把class解析成beanDefinition,然后在实例化bean的时候,再加载类,这个步骤的优势在于,减少spring启动的时间,如果项目工程较大,拥有的class比较多,那么直接去加载类就会使得启动变慢

为什么需要合并

java类,有父类,子类,子类继承父类的属性和方法,然后子类拥有父类的属性和方法,而beanDefinition解析的class信息,没有父类的信息,所以要进行合并。

后置处理器的作用

后置处理器可以让我们在spring在实例化bean时,可以对bean的生成进行一些自定义的操作。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/03/12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • Bean的生命周期
    • 生成BeanDefinition
      • 合并beanDefinition
        • 加载类
          • 实例化前
            • 推断构造方法
              • 实例化
                • BeanDefinition后置处理器处理
                  • 填充属性
                    • 执行aware
                      • 初始化前
                        • 初始化
                          • 初始化后
                          • Bean 的销毁
                          • 总结
                          相关产品与服务
                          容器服务
                          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档