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

2023-10-24 18:47:09 浏览数 (1)

前言

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的生成进行一些自定义的操作。

0 人点赞