• Spring源码:Bean生命周期(四)


    前言

    在之前的文章中,我们介绍了 Bean 的核心概念、Bean 定义的解析过程以及 Bean 创建的准备工作。在今天的文章中,我们将深入探讨 Bean 的创建过程,并主要讲解 createBean 方法的实现。在这个过程中,我们将了解 Bean 的实例化、属性注入、初始化和销毁等步骤,以及各个步骤的具体实现细节。通过本文的学习,读者将能够更深入地理解 Spring 框架中 Bean 的创建过程,从而为后续的学习和实践打下坚实的基础。好了,我们开始!

    createBean

    前面我们说过,最开始的bean定义(合并后的),解析类的元数据时,用到的是ASM技术并不会真正开始解析class文件,所以也只是提取出来bean的name值作为beanClass属性,知道这个前提,那么这一步就好说了,下面是他的源码:

    	@Override
    	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    			throws BeanCreationException {
    
    		RootBeanDefinition mbdToUse = mbd;
    		
    		// 马上就要实例化Bean了,确保beanClass被加载了
    		Class resolvedClass = resolveBeanClass(mbd, beanName);
    		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    			mbdToUse = new RootBeanDefinition(mbd);
    			mbdToUse.setBeanClass(resolvedClass);
    		}
    
    		// Prepare method overrides.
    		try {
    			mbdToUse.prepareMethodOverrides();
    		}
    
    		try {
    			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    			// 实例化前
    			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    			if (bean != null) {
    				return bean;
    			}
    		}
    
    		try {
    			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    			......
    			return beanInstance;
    		}
    	}
    
    1. resolveBeanClass:真正的开始加载bean。
    2. mbdToUse.prepareMethodOverrides();和@lookUp注解有关系,不看
    3. resolveBeforeInstantiation:实例化前的BeanPostProcessors,如果初始化了那么就返回了,不走其他创建逻辑了。
    4. doCreateBean:正常开始实例化、初始化bean。

    resolveBeanClass

    如果当前bean被加载了,那么直接返回了,如果没加载那么开始解析当前bean

    	@Nullable
    	protected Class resolveBeanClass(RootBeanDefinition mbd, String beanName, Class... typesToMatch)
    			throws CannotLoadBeanClassException {
    
    		try {
    			// 如果beanClass被加载了
    			if (mbd.hasBeanClass()) {
    				return mbd.getBeanClass();
    			}
    
    			// 如果beanClass没有被加载
    			if (System.getSecurityManager() != null) {
    				return AccessController.doPrivileged((PrivilegedExceptionAction>)
    						() -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
    			}
    			else {
    				return doResolveBeanClass(mbd, typesToMatch);
    			}
    		}
    	}
    

    是否已经加载的判断依据就是我说的,是否是class,正常下我们的beanClass为字符串,也就是beanname,看下源码:

    public boolean hasBeanClass() {
    		return (this.beanClass instanceof Class);
    	}
    

    doResolveBeanClass

    真正开始加载class,如果需要加载class那肯定离不开类加载器,看下源码:

    	@Nullable
    	private Class doResolveBeanClass(RootBeanDefinition mbd, Class... typesToMatch)
    			throws ClassNotFoundException {
    
    		ClassLoader beanClassLoader = getBeanClassLoader();
    		ClassLoader dynamicLoader = beanClassLoader;
    		boolean freshResolve = false;
    
    		if (!ObjectUtils.isEmpty(typesToMatch)) {
    			// When just doing type checks (i.e. not creating an actual instance yet),
    			// use the specified temporary class loader (e.g. in a weaving scenario).
    			ClassLoader tempClassLoader = getTempClassLoader();
    			if (tempClassLoader != null) {
    				dynamicLoader = tempClassLoader;
    				freshResolve = true;
    				if (tempClassLoader instanceof DecoratingClassLoader) {
    					DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
    					for (Class typeToMatch : typesToMatch) {
    						dcl.excludeClass(typeToMatch.getName());
    					}
    				}
    			}
    		}
    
    		String className = mbd.getBeanClassName();
    		if (className != null) {
    			// 解析Spring表达式,有可能直接返回了一个Class对象
    			Object evaluated = evaluateBeanDefinitionString(className, mbd);
    			if (!className.equals(evaluated)) {
    				// A dynamically resolved expression, supported as of 4.2...
    				if (evaluated instanceof Class) {
    					return (Class) evaluated;
    				}
    				else if (evaluated instanceof String) {
    					className = (String) evaluated;
    					freshResolve = true;
    				}
    				else {
    					throw new IllegalStateException("Invalid class name expression result: " + evaluated);
    				}
    			}
    			if (freshResolve) {
    				// When resolving against a temporary class loader, exit early in order
    				// to avoid storing the resolved Class in the bean definition.
    				if (dynamicLoader != null) {
    					try {
    						return dynamicLoader.loadClass(className);
    					}
    					catch (ClassNotFoundException ex) {
    						if (logger.isTraceEnabled()) {
    							logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
    						}
    					}
    				}
    				return ClassUtils.forName(className, dynamicLoader);
    			}
    		}
    
    		// Resolve regularly, caching the result in the BeanDefinition...
    		return mbd.resolveBeanClass(beanClassLoader);
    	}
    

    我们自己的bean走不了这么多逻辑,我们既没有传typesToMatch,也没有写Spring表达式,所以就是拿了一个类加载器和使用类加载器加载class,如果我们没有自定义类加载器那么使用默认的,看下源码:

    	@Nullable
    	public static ClassLoader getDefaultClassLoader() {
    		ClassLoader cl = null;
    
    		// 优先获取线程中的类加载器
    		try {
    			cl = Thread.currentThread().getContextClassLoader();
    		}
    		catch (Throwable ex) {
    			// Cannot access thread context ClassLoader - falling back...
    		}
    
    		// 线程中类加载器为null的情况下,获取加载ClassUtils类的类加载器
    		if (cl == null) {
    			// No thread context class loader -> use class loader of this class.
    			cl = ClassUtils.class.getClassLoader();
    			if (cl == null) {
    				// getClassLoader() returning null indicates the bootstrap ClassLoader
    				// 加入ClassUtils是被Bootstrap类加载器加载的,则获取系统类加载器
    				try {
    					cl = ClassLoader.getSystemClassLoader();
    				}
    				catch (Throwable ex) {
    					// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
    				}
    			}
    		}
    		return cl;
    	}
    
    1. 优先获取线程中的类加载器
    2. 线程中类加载器为null的情况下,获取加载ClassUtils类的类加载器,这里Spring注意到了java的boostrap加载器,所以会有为null的情况
    3. 如果为null,那么使用ClassUtils当前工具类使用的是哪个加载器
    4. 假如ClassUtils是被Bootstrap类加载器加载的,则获取系统类加载器
    	public Class resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
    		String className = getBeanClassName();
    		if (className == null) {
    			return null;
    		}
    		Class resolvedClass = ClassUtils.forName(className, classLoader);
    		this.beanClass = resolvedClass;
    		return resolvedClass;
    	}
    
    	public String getBeanClassName() {
    		Object beanClassObject = this.beanClass;
    		if (beanClassObject instanceof Class) {
    			return ((Class) beanClassObject).getName();
    		}
    		else {
    			return (String) beanClassObject;
    		}
    	}
    

    通过这一步也可以看出bean定义中最初的beanClass属性,都是String类型的beanname

    resolveBeforeInstantiation

    这一步走的是实例化前的工作,当然如果你想在这一步中直接返回实体类也可,而且最离谱的是Spring并没有校验你返回的类是否是当前beanname的类,可以看下源码:

    	@Nullable
    	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    		Object bean = null;
    		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
    			// Make sure bean class is actually resolved at this point.
    			// synthetic表示合成,如果某些Bean式合成的,那么则不会经过BeanPostProcessor的处理
    			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    				Class targetType = determineTargetType(beanName, mbd);
    				if (targetType != null) {
    					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
    					if (bean != null) {
    						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
    					}
    				}
    			}
    			mbd.beforeInstantiationResolved = (bean != null);
    		}
    		return bean;
    	}
    
    1. hasInstantiationAwareBeanPostProcessors:直接从缓存list中获取有关实例化的BeanPostProcessors,这里是一个优化,要不然每次获取有关实例化的BeanPostProcessors都是遍历整个BeanPostProcessors再加个校验
    2. determineTargetType:获取类
    3. applyBeanPostProcessorsBeforeInstantiation:执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation的方法,该方法可以返回bean。
    4. postProcessAfterInstantiation:执行BeanPostProcessor的postProcessAfterInstantiation的方法,正常我们的bean不会走到这里,因为实例化前根本没有创建出来bean,所以也就是bean != null一直为false

    当然除非你自己写一个InstantiationAwareBeanPostProcessors,其实真没看见这么玩的,主要是没有啥意义,比如这样:

    @Component
    public class MyInstantiationAwareBeanPostProcessors implements InstantiationAwareBeanPostProcessor {
    
    	@Override
    	public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
    		if (beanName.equals("userService")) {
    			System.out.println("MyInstantiationAwareBeanPostProcessors.postProcessBeforeInstantiation");
    			return new First();
    		}
    		return null;
    	}
    
    	@Override
    	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    		if (beanName.equals("userService")) {
    			System.out.println("MyInstantiationAwareBeanPostProcessors.postProcessAfterInitialization");
    			return new Second();
    		}
    		return bean;
    	}
    }
    

    再坚持一下,让我把实例化过程先讲完!

    现在的逻辑已经走完了实例化前的postProcessBeforeInstantiation方法,那么现在我们的bean要进行实例化了,

    	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    			throws BeanCreationException {
    
    		// 实例化bean
    		// Instantiate the bean.
    		BeanWrapper instanceWrapper = null;
    		if (mbd.isSingleton()) {
    			// 有可能在本Bean创建之前,就有其他Bean把当前Bean给创建出来了(比如依赖注入过程中)
    			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    		}
    		if (instanceWrapper == null) {
    			// 创建Bean实例
    			instanceWrapper = createBeanInstance(beanName, mbd, args);
    		}
    		Object bean = instanceWrapper.getWrappedInstance();
    		Class beanType = instanceWrapper.getWrappedClass();
    		if (beanType != NullBean.class) {
    			mbd.resolvedTargetType = beanType;
    		}
    
    		// 后置处理合并后的BeanDefinition
    		// Allow post-processors to modify the merged bean definition.
    		synchronized (mbd.postProcessingLock) {
    			if (!mbd.postProcessed) {
    				try {
    					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    				}
    				catch (Throwable ex) {
    					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    							"Post-processing of merged bean definition failed", ex);
    				}
    				mbd.postProcessed = true;
    			}
    		}
    
    		// 为了解决循环依赖提前缓存单例创建工厂
    		// Eagerly cache singletons to be able to resolve circular references
    		// even when triggered by lifecycle interfaces like BeanFactoryAware.
    		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    				isSingletonCurrentlyInCreation(beanName));
    		if (earlySingletonExposure) {
    			if (logger.isTraceEnabled()) {
    				logger.trace("Eagerly caching bean '" + beanName +
    						"' to allow for resolving potential circular references");
    			}
    			// 循环依赖-添加到三级缓存
    			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    		}
    
    		// Initialize the bean instance.
    		Object exposedObject = bean;
    		try {
    			// 属性填充
    			populateBean(beanName, mbd, instanceWrapper);
          ......
    		return exposedObject;
    	}
    

    跟这篇无关的内容能删除的都删除了,主要有这几步我们需要注意下:

    1. createBeanInstance:创建实例,前提是之前没有创建过
    2. applyMergedBeanDefinitionPostProcessors:找到注入点,比如AutowiredAnnotationBeanPostProcessor(@Autowired、@Value、@Inject)和CommonAnnotationBeanPostProcessor(@Resource),这在实例化前和实例化后方法中间夹了一个处理合并bean定义的逻辑,注意一下
    3. addSingletonFactory:添加缓存,用来解决循环依赖,以后单独讲解
    4. populateBean:这一方法主要是属性填充也就是依赖注入的,但是官方把实例化后的PostProcessors方法写到这里了,所以也得贴出来,但是我们只看实例化相关的。

    createBeanInstance

    	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    		// Make sure bean class is actually resolved at this point.
    		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());
    		}
    
    		// BeanDefinition中添加了Supplier,则调用Supplier来得到对象
    		Supplier instanceSupplier = mbd.getInstanceSupplier();
    		if (instanceSupplier != null) {
    			return obtainFromSupplier(instanceSupplier, beanName);
    		}
    
    		// @Bean对应的BeanDefinition
    		if (mbd.getFactoryMethodName() != null) {
    			return instantiateUsingFactoryMethod(beanName, mbd, args);
    		}
        ......
    		return instantiateBean(beanName, mbd);
    	}
    
    1. resolveBeanClass:之前讲解过了,不重复讲了,就是拿到class
    2. obtainFromSupplier:通过Supplier函数获取bean,前提是你得声明bean定义
    3. instantiateUsingFactoryMethod:这种是使用@Bean方法实例化对象,
    4. 后面省略了推断构造方法进行实例化对象,以后单独讲解推断构造方法

    obtainFromSupplier

    这一步其实我们用到的很少,主要是考虑到Spring自动注入的开销,我们自己可以就行实例化而已,比如我们这样写照样可以获取bean,但是不会由Spring帮我们注入,得靠自己了:

    //		 创建一个Spring容器
    		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
    		AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
    		beanDefinition.setBeanClass(UserService.class);
    		beanDefinition.setInstanceSupplier(() -> new UserService());
    		applicationContext.registerBeanDefinition("userService", beanDefinition);
    		UserService userService = (UserService) applicationContext.getBean(UserService.class);
    		userService.test();
    

    其实用法和@bean注解相似,除了减少Spring自动注入的开销,实在没想到有啥用

    instantiateUsingFactoryMethod

    该方法内部逻辑很多,为了更加直观的展现,只贴出关键代码:

    	@Override
    	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
    			@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
    
    		try {
    			if (System.getSecurityManager() != null) {
    				AccessController.doPrivileged((PrivilegedAction) () -> {
    					ReflectionUtils.makeAccessible(factoryMethod);
    					return null;
    				});
    			}
    			else {
    				ReflectionUtils.makeAccessible(factoryMethod);
    			}
    
    			Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
    			try {
    				currentlyInvokedFactoryMethod.set(factoryMethod);
    				// factoryBean就是AppConfig的代理对象(如果加了@Configuration)
    				// factoryMethod就是@Bean修饰的方法
    				Object result = factoryMethod.invoke(factoryBean, args);
    				if (result == null) {
    					result = new NullBean();
    				}
    				return result;
    			}
    			finally {
    				if (priorInvokedFactoryMethod != null) {
    					currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
    				}
    				else {
    					currentlyInvokedFactoryMethod.remove();
    				}
    			}
    		}
    		......
    	}
    
    

    比如我们定义的配置类中有很多@Bean形式的方法,最终Spring会直接invoke调用被@Bean修饰的方法从而实现实例化对象。

    applyMergedBeanDefinitionPostProcessors

    这里关于MergedBeanDefinitionPostProcessors的实现类不全讲解了,主要讲解下工作常用的注解AutowiredAnnotationBeanPostProcessor,他是用来解析@Autowired、@Value、@Inject,看下他的默认源码:

    public AutowiredAnnotationBeanPostProcessor() {
    		this.autowiredAnnotationTypes.add(Autowired.class);
    		this.autowiredAnnotationTypes.add(Value.class);
    		try {
    			this.autowiredAnnotationTypes.add((Classextends Annotation>)
    					ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
    		}
    	}
    

    看下他主要做了那些工作,关键代码附上:

    private InjectionMetadata buildAutowiringMetadata(final Class clazz) {
    	// 如果一个Bean的类型是String...,那么则根本不需要进行依赖注入
    	if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
    		return InjectionMetadata.EMPTY;
    	}
    
    	List elements = new ArrayList<>();
    	Class targetClass = clazz;
    
    	do {
    		final List currElements = new ArrayList<>();
    
    		// 遍历targetClass中的所有Field
    		ReflectionUtils.doWithLocalFields(targetClass, field -> {
    			// field上是否存在@Autowired、@Value、@Inject中的其中一个
    			MergedAnnotation ann = findAutowiredAnnotation(field);
    			if (ann != null) {
    				// static filed不是注入点,不会进行自动注入
    				if (Modifier.isStatic(field.getModifiers())) {
    					if (logger.isInfoEnabled()) {
    						logger.info("Autowired annotation is not supported on static fields: " + field);
    					}
    					return;
    				}
    
    				// 构造注入点
    				boolean required = determineRequiredStatus(ann);
    				currElements.add(new AutowiredFieldElement(field, required));
    			}
    		});
    
    		// 遍历targetClass中的所有Method
    		ReflectionUtils.doWithLocalMethods(targetClass, method -> {
    
    			Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
    			if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
    				return;
    			}
    			// method上是否存在@Autowired、@Value、@Inject中的其中一个
    			MergedAnnotation ann = findAutowiredAnnotation(bridgedMethod);
    			if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
    				// static method不是注入点,不会进行自动注入
    				if (Modifier.isStatic(method.getModifiers())) {
    					if (logger.isInfoEnabled()) {
    						logger.info("Autowired annotation is not supported on static methods: " + method);
    					}
    					return;
    				}
    				// set方法最好有入参
    				if (method.getParameterCount() == 0) {
    					if (logger.isInfoEnabled()) {
    						logger.info("Autowired annotation should only be used on methods with parameters: " +
    									method);
    					}
    				}
    				boolean required = determineRequiredStatus(ann);
    				PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
    				currElements.add(new AutowiredMethodElement(method, required, pd));
    			}
    		});
    
    		elements.addAll(0, currElements);
    		targetClass = targetClass.getSuperclass();
    	}
    	while (targetClass != null && targetClass != Object.class);
    
    	return InjectionMetadata.forElements(elements, clazz);
    }
    
    1. 如果一个Bean的类型是String,那么则根本不需要进行依赖注入
    2. 遍历targetClass中的所有Field,是否存在@Autowired、@Value、@Inject中的其中一个,如果是static字段则不注入否则记录构造注入点
    3. 遍历targetClass中的所有Method,是否存在@Autowired、@Value、@Inject中的其中一个,如果是static字段则不注入否则记录构造注入点

    populateBean

    这个方法主要是属性填充,也就是所说的依赖注入的过程,我们不讲解这一部分,只讲解关于实例化最后的阶段postProcessAfterInstantiation方法,方法进来第一步就是调用postProcessAfterInstantiation方法。但是只看Spring源码的话,其实并没有太多实现,都是默认实现方法:

    		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
    				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    					return;
    				}
    			}
    		}
    

    总结

    在本文中,我们深入探讨了 Spring 框架中 Bean 的实例化过程,关于某些细节以后我会单独拿出一篇文章单独讲解,我们来总结下实例化都做了哪些事情:

    1. 先从bean定义中加载当前类,因为最初Spring使用ASM技术解析元数据时只获取了当前类的名称
    2. 寻找所有InstantiationAwareBeanPostProcessors实现类,并调用实例化前的方法postProcessBeforeInstantiation
    3. 进行实例化,这里会使用构造方法进行实例化
    4. 调用applyMergedBeanDefinitionPostProcessors找到所有MergedBeanDefinitionPostProcessors的实现类,比如我们的注入点(@Autowired等)
    5. 寻找所有InstantiationAwareBeanPostProcessors实现类,并调用实例化后的方法postProcessAfterInstantiation

    通过本文的学习,读者将能够更深入地了解 Spring 框架中 Bean 的实例化过程,为后续的学习和实践打下坚实的基础。下一篇文章,我们将深入探讨 Bean 的初始化过程。

    公众号
  • 相关阅读:
    codeforces:C. Set Construction【构造 + 入度观察】
    训练神经网络的各种优化算法【文末赠书】
    Redis实现分布式锁
    飞睿智能高精度、低功耗测距,无线室内定位UWB芯片如何改变智能家居
    第八章 异常处理 ① 笔记
    MySQL之InnoDB引擎(六)
    Linux开发——Linux 文件系统简介(四)
    基于51单片机温湿度控制器proteus仿真设计
    如何使用SMS向客户传递服务信息?指南在这里!
    WhatsApp自动营销软件是真实的吗?对做外贸有帮助吗?
  • 原文地址:https://www.cnblogs.com/guoxiaoyu/p/17402789.html