4、Spring源码-bean的生命周期

烟雨 4年前 (2021-07-15) 阅读数 12230 #Spring源码
文章标签 Spring

一、生成DeanDefinition

Spring启动的时候会进行扫描,会先通过doScan()方法调用findCandidateComponents(basePackage);再调用ClassPathScanningCandidateComponentProvider#scanCandidateComponents(basePackage)扫描某个包路径

//扫描class
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    Set<BeanDefinition> candidates = new LinkedHashSet<>();
    try {
        //获取basePackage所有的文件资源
        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 (traceEnabled) {
                logger.trace("Scanning " + resource);
            }
            if (resource.isReadable()) {
                try {
                    //获取类元素读取器
                    MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                    if (isCandidateComponent(metadataReader)) {
                        //生成ScannedGenericBeanDefinition
                        ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                        sbd.setResource(resource);
                        sbd.setSource(resource);
                        if (isCandidateComponent(sbd)) {
                            if (debugEnabled) {
                                logger.debug("Identified candidate component class: " + resource);
                            }
                            //放入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 (Throwable ex) {
                    throw new BeanDefinitionStoreException(
                        "Failed to read candidate component class: " + resource, ex);
                }
            }
            else {
                if (traceEnabled) {
                    logger.trace("Ignored because not readable: " + resource);
                }
            }
        }
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
    }
    return candidates;
}

并得到BeanDefinition的Set集合。如图:

image.png

Spring扫描底层流程:
  1. 首先,通过ResourcePatternResolver获得指定包路径下的所有.class文件(.class文件会包装成了Resource对象)。

  2. 遍历每个Resource对象。

  3. 利用MetadataReaderFactory解析Resource对象得到MetadataReader(类元素读取器)(MetadataReaderFactory具体的实现类为CachingMetadataReaderFactory,MetadataReader的具体实现类为SimpleMetadataReader)

  4. 利用MetadataReader进行excludeFilters和includeFilters,以及条件注解@Conditional的筛选(@Conditional条件注解,某个类上是否存在@Conditional注解,如果存在则调用注解中所指定的类的match方法进行匹配,匹配成功则通过筛选,匹配失败则pass掉)。

  5. 筛选通过后,基于metadataReader(类元素读取器)生成ScannedGenericBeanDefinition。

  6. 再基于metadataReader判断是不是对应的类是不是接口或抽象类。

  7. 如果筛选通过,那么就表示扫描到了一个Bean,将ScannedGenericBeanDefinition加入结果集。

CachingMetadataReaderFactory解析某个.class文件得到MetadataReader对象是利用的ASM技术,并没有加载这个类到JVM。

最终得到的ScannedGenericBeanDefinition对象,ScannedGenericBeanDefinition的beanClass属性存储的是当前类的名字,而不是class对象(beanClass属性的类型是Object,它即可以存储类的名字,也可以存储class对象)

二、合并DeanDefinition

通过扫描得到所有BeanDefinition之后,就可以根据BeanDefinition创建Bean对象了,但是在Spring中支持父子BeanDefinition,需要进行合并处理(后面处理的BeanDefinition都是合并后的BeanDefinition)!
父子
BeanDefinition举例:
<!-- 这么定义的情况下,child是单例Bean。-->
<bean id="parent" class="com.zender.service.Parent" scope="prototype"/>
<bean id="child" class="com.zender.service.Child"/>

<!-- 这么定义的情况下,child就是原型Bean。
	 因为child的父BeanDefinition是parent,所以会继承parent上所定义的scope属性。
-->
<bean id="parent" class="com.zender.service.Parent" scope="prototype"/>
<bean id="child" class="com.zender.service.Child" parent="parent"/>

在根据child来生成Bean对象之前,需要进行BeanDefinition的合并,得到完整的child的BeanDefinition。

AbstractBeanFactory#getMergedBeanDefinition()

protected RootBeanDefinition getMergedBeanDefinition(
			String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
			throws BeanDefinitionStoreException {

		synchronized (this.mergedBeanDefinitions) {
			RootBeanDefinition mbd = null;

			// Check with full lock now in order to enforce the same merged instance.
			if (containingBd == null) {
				mbd = this.mergedBeanDefinitions.get(beanName);
			}

			if (mbd == null) {
				// 先判断当前这个BeanDefiniton有没有parent
				if (bd.getParentName() == null) {
					// Use copy of given root bean definition.
					// 如果没有,将当前BeanDefinition的内容拷贝到新的RootBeanfinition里,然后返回
					if (bd instanceof RootBeanDefinition) {
						mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
					}
					else {
						mbd = new RootBeanDefinition(bd);
					}
				}
				else {
					// Child bean definition: needs to be merged with parent.
					BeanDefinition pbd;
					try {
						String parentBeanName = transformedBeanName(bd.getParentName());
						if (!beanName.equals(parentBeanName)) {
							// 递归,可能还有parent
							pbd = getMergedBeanDefinition(parentBeanName);
						}
						else {
							BeanFactory parent = getParentBeanFactory();
							if (parent instanceof ConfigurableBeanFactory) {
								// 递归,可能还有parent
								pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
							}
							else {
								throw new NoSuchBeanDefinitionException(parentBeanName,
										"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
										"': cannot be resolved without an AbstractBeanFactory parent");
							}
						}
					}
					catch (NoSuchBeanDefinitionException ex) {
						throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
								"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
					}
					// Deep copy with overridden values.
					// 创建出父beanDefinition
					mbd = new RootBeanDefinition(pbd);
					// 子beanDefinition的属性覆盖父beanDefinition的属性(合并),同时也会得到父beanDefinition的属性。
					mbd.overrideFrom(bd);
				}

				// Set default singleton scope, if not configured before.
				if (!StringUtils.hasLength(mbd.getScope())) {
					mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
				}

				// A bean contained in a non-singleton bean cannot be a singleton itself.
				// Let's correct this on the fly here, since this might be the result of
				// parent-child merging for the outer bean, in which case the original inner bean
				// definition will not have inherited the merged outer bean's singleton status.
				if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
					mbd.setScope(containingBd.getScope());
				}

				// Cache the merged bean definition for the time being
				// (it might still get re-merged later on in order to pick up metadata changes)
				if (containingBd == null && isCacheBeanMetadata()) {
					this.mergedBeanDefinitions.put(beanName, mbd);
				}
			}

			return mbd;
		}
	}

三、加载类

BeanDefinition合并之后,就可以去创建Bean对象了,而创建Bean就必须实例化对象,而实例化就必须先加载当前BeanDefinition所对应的class。
AbstractAutowireCapableBeanFactory#createBean()方法中,一开始就会调用:
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);

该方法是实现如下:

@Nullable
protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
    throws CannotLoadBeanClassException {
    try {
        if (mbd.hasBeanClass()) {
            return mbd.getBeanClass();
        }
        if (System.getSecurityManager() != null) {
            return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
                                                 doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
        }
        else {
            return doResolveBeanClass(mbd, typesToMatch);
        }
    }
    catch (PrivilegedActionException pae) {
        ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
        throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
    }
    catch (ClassNotFoundException ex) {
        throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
    }
    catch (LinkageError ex) {
        throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
    }
}

如果beanClass属性的类型是Class,那么就直接返回,如果不是,则会根据类名进行加载(doResolveBeanClass方法所做的事情)

会利用BeanFactory所设置的类加载器来加载类,如果没有设置,则默认使用ClassUtils.getDefaultClassLoader()所返回的类加载器来加载。

ClassUtils.getDefaultClassLoader()大致步骤

  1. 优先返回当前线程中的ClassLoader。

  2. 线程中类加载器为null的情况下,返回ClassUtils类的类加载器。

  3. 如果ClassUtils类的类加载器为空,那么则表示是Bootstrap类加载器加载的ClassUtils类,那么则返回系统类加载器。

四、实例化前(实现InstantiationAwareBeanPostProcessor接口)

当前BeanDefinition对应的类成功加载后,就可以实例化对象了。

但是在Spring中,实例化对象之前,Spring提供了一个扩展点,允许用户来控制是否在某个或某些Bean实例化之前做一些启动动作。

扩展点叫InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(),也就是实现InstantiationAwareBeanPostProcessor接口,比如:

@Component
public class ZenderBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
			System.out.println("实例化前");
		}
		return null;
	}
}
如上代码会导致,在userService这个Bean实例化前,会进行打印:实例化前。
注意,postProcessBeforeInstantiation()方法是有返回值的,可以这么用:
@Component
public class ZenderBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
			System.out.println("实例化前");
			return new UserService();
		}
		return null;
	}
}

userService这个Bean,在实例化前会直接返回一个由自己定义的UserService对象。

如果是这样,表示不需要Spring来实例化了,并且后续的Spring依赖注入也不会进行了,会跳过一些步骤,直接执行初始化后这一步。

五、实例化

在这个步骤中就会根据BeanDefinition去创建一个对象了。

5.1、情况1:使用Supplier创建对象

首先判断BeanDefinition中是否设置了Supplier,如果设置了则调用Supplier的get()得到对象。
Supplier如何使用:
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setInstanceSupplier(new Supplier<Object>() {
	@Override
	public Object get() {
		return new UserService();
	}
});
context.registerBeanDefinition("userService", beanDefinition);

5.2、情况2:使用工厂方法创建对象

如果没有设置Supplier,则检查BeanDefinition中是否设置了factoryMethod,也就是工厂方法。
有两种方式可以设置factoryMethod(工厂方法),比如:

方式1:factory-method指定

<bean id="userService" class="com.zhouyu.service.UserService" factory-method="createUserService" />
public class UserService {
	public static UserService createUserService() {
		System.out.println("执行createUserService()");
		UserService userService = new UserService();
		return userService;
	}
	public void test() {
		System.out.println("test");
	}
}

方式2:factory-bean指定工厂Bean,factory-method指定工厂方法

<bean id="commonService" class="com.zhouyu.service.CommonService"/>
<bean id="userService1" factory-bean="commonService" factory-method="createUserService" />
public class CommonService {
	public UserService createUserService() {
		return new UserService();
	}
}

Spring发现当前BeanDefinition方法设置了工厂方法后,就会区分这两种方式,然后调用工厂方法得到对象。

注意:

我们通过@Bean所定义的BeanDefinition,是存在factoryMethod和factoryBean的,也就是和上面的方式二非常类似,@Bean所注解的方法就是factoryMethod,AppConfig对象就是factoryBean。如果@Bean所所注解的方法是static的,那么对应的就是方式一。

5.3、情况3:推断构造方法

在推断构造方法逻辑中除开会去选择构造方法以及查找入参对象意外,会还判断是否在对应的类中是否存在使用@Lookup注解了方法。如果存在则把该方法封装为LookupOverride对象并添加到BeanDefinition中。

在实例化时,如果判断出来当前BeanDefinition中没有LookupOverride,那就直接用构造方法反射得到一个实例对象。如果存在LookupOverride对象,也就是类中存在@Lookup注解了的方法,那就会生成一个代理对象。

@Lookup注解就是方法注入

@Component
public class UserService {

	private OrderService orderService;

	public void test() {
		OrderService orderService = createOrderService();
		System.out.println(orderService);
	}

	@Lookup("orderService")
	public OrderService createOrderService() {
		return null;
	}
}

六、BeanDefinition的后置处理(BeanDefinitionPostProcessor)

Bean对象实例化出来之后,接下来就应该给对象的属性赋值了。

在真正给属性赋值之前,Spring又提供了一个扩展点MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition(),可以对此时的BeanDefinition进行加工,比如:

@Component
public class ZenderMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		if ("userService".equals(beanName)) {
			beanDefinition.getPropertyValues().add("orderService", new OrderService());
		}
	}
}

在Spring源码中,AutowiredAnnotationBeanPostProcessor就是一个MergedBeanDefinitionPostProcessor,它的postProcessMergedBeanDefinition()中会去查找注入点,并缓存在AutowiredAnnotationBeanPostProcessor对象的一个Map中(injectionMetadataCache)。

七、实例化后

在处理完BeanDefinition后,Spring又设计了一个扩展点:InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation(),比如:

@Component
public class ZenderInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
			UserService userService = (UserService) bean;
			userService.test();
		}
		return true;
	}
}

上述代码就是对userService所实例化出来的对象进行处理。

八、自动注入(依赖注入)

依赖注入的主要逻辑在AbstractAutowireCapableBeanFactory#populateBean()中,详情看:5、Spring源码-依赖注入

九、处理属性

这个步骤中,就会处理@Autowired、@Resource、@Value等注解,也是通过InstantiationAwareBeanPostProcessor#postProcessProperties()扩展点来实现的,比如我们甚至可以实现一个自己的自动注入功能,比如:

@Component
public class ZenderInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
			for (Field field : bean.getClass().getFields()) {
				if (field.isAnnotationPresent(ZhouyuInject.class)) {
					field.setAccessible(true);
					try {
						field.set(bean, "123");
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					}
				}
			}
		}
		return pvs;
	}
}

十、执行Aware

完成了属性赋值之后,Spring会执行一些回调,包括:

  1. BeanNameAware:回传beanName给bean对象。

  2. BeanClassLoaderAware:回传classLoader给bean对象。

  3. BeanFactoryAware:回传beanFactory给对象。

十一、初始化前(BeanPostProcessor)

初始化前,也是Spring提供的一个扩展点:BeanPostProcessor#postProcessBeforeInitialization(),比如:

@Component
public class ZenderBeanPostProcessor implements BeanPostProcessor {
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
			System.out.println("初始化前");
		}
		return bean;
	}
}

十二、初始化

  1. 查看当前Bean对象是否实现了InitializingBean接口,如果实现了就调用其afterPropertiesSet()方法

  2. 执行BeanDefinition中指定的初始化方法。

十三、初始化后

这是Bean创建生命周期中的最后一个步骤,也是Spring提供的一个扩展点:BeanPostProcessor#postProcessAfterInitialization(),比如:

@Component
public class ZenderBeanPostProcessor implements BeanPostProcessor {
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
			System.out.println("初始化后");
		}
		return bean;
	}
}
总结
Spring创建Bean的生命周期如下:
  1. 生成BeanDefinition。

  2. 合并BeanDefinition。

  3. 加载类。

  4. 实例化前(实现InstantiationAwareBeanPostProcessor接口) 。

  5. 实例化(Supplier\工厂方法创建对象\推断构造方法)。

  6. BeanDefinition都后置处理(实现MergedBeanDefinitionPostProcessor接口)。

  7. 实例化后(实现InstantiationAwareBeanPostProcessor接口)。

  8. 自动注入。

  9. 处理属性(实现InstantiationAwareBeanPostProcessor接口,可实现自己的属性处理)。

  10. 执行Aware。

  11. 初始化前(实现BeanPostProcessor接口)。

  12. 初始化。

  13. 初始化后(实现BeanPostProcessor接口)。

总结更新2022-05-18,相比上面,更详细。

Spring创建Bean的生命周期如下:
  1. Bean元信息配置阶段:获取Bean元信息,Bean原信息定义方式(API的方式、xml方式、properties文件的方式、注解方式)。

  2. Bean元信息解析阶段:利用Bean元信息,生成BeanDefinition。

  3. Spring Bean注册阶段:利用生成BeanDefinition去注册Bean。

  4. BeanDefinition合并阶段:合并具有父子关系bean。最终得到一个RootBeanDefinition。

  5. Bean Class加载阶段:这个阶段就是将bean的class名称转换为Class类型的对象。

  6. Bean实例化阶段:

    1. Bean实例化前操作:会调用InstantiationAwareBeanPostProcessor#postProcessBeforeInitialization()方法。

    2. 实例化操作:会调用SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors()方法逻辑,如何实例化(Supplier\工厂方法创建对象\推断构造方法)

    3. BeanDefinition的后置处理:调用MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition()方法。

  7. Bean属性设置阶段:

    1. Bean实例化后:会调用InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation()方法。

    2. Bean属性赋值前:会调用InstantiationAwareBeanPostProcessor#postProcessProperties()方法。

    3. Bean属性赋值阶段:循环处理PropertyValues中的属性值信息,通过反射调用set方法将属性的值设置到bean实例中。

  8. Bean初始化阶段:

    1. Bean Aware接口回调:如果Bean实现了BeanNameAware、 BeanClassLoaderAware、 BeanFactoryAware、EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware。会依次调用相应实现的接口方法。

    2. Bean初始化前操作:会调用BeanPostProcessor#postProcessBeforeInitialization()方法。

    3. Bean初始化阶段:

      1. 调用InitializingBean#afterPropertiesSet()方法。

      2. 调用定义bean的时候指定的初始化方法。

    4. Bean初始化后阶段:调用BeanPostProcessor#postProcessAfterInitialization()方法。

  9. 所有单例bean初始化完成后阶段:所有单例bean实例化完成之后,spring会回调SmartInitializingSingleton#afterSingletonsInstantiated()方法。

  10. Bean使用阶段。

  11. Bean销毁阶段:

    1. 轮询beanPostProcessors列表,如果是DestructionAwareBeanPostProcessor这种类型的,会调用其内部的postProcessBeforeDestruction()方法。

    2. 如果bean实现了org.springframework.beans.factory.DisposableBean接口,会调用这个接口中destroy()方法。

    3. 调用bean自定义的销毁方法。


版权声明

非特殊说明,本文由Zender原创或收集发布,欢迎转载。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

作者文章
热门