第九章:Spring Bean生命周期(Bean Lifecycle)

Spring Bean 元信息解析阶段:BeanDefinition的配置与扩展第九章:Spring Bean生命周期(Bean Lifecycle)_第1张图片

public class BeanMetadataConfigurationDemo {

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 实例化基于 Properties 资源 BeanDefinitionReader
        PropertiesBeanDefinitionReader beanDefinitionReader = new PropertiesBeanDefinitionReader(beanFactory);
        String location = "META-INF/user.properties";
        // 基于 ClassPath 加载 properties 资源
        Resource resource = new ClassPathResource(location);
        // 指定字符编码 UTF-8
        EncodedResource encodedResource = new EncodedResource(resource, "UTF-8");
        int beanNumbers = beanDefinitionReader.loadBeanDefinitions(encodedResource);
        System.out.println("已加载 BeanDefinition 数量:" + beanNumbers);
        // 通过 Bean Id 和类型进行依赖查找
        User user = beanFactory.getBean("user", User.class);
        System.out.println(user);
    }

}

Spring Bean 元信息解析阶段:BeanDefinition的解析第九章:Spring Bean生命周期(Bean Lifecycle)_第2张图片`public class AnnotatedBeanDefinitionParsingDemo {

public static void main(String[] args) {
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    // 基于 Java 注解的 AnnotatedBeanDefinitionReader 的实现
    AnnotatedBeanDefinitionReader beanDefinitionReader = new AnnotatedBeanDefinitionReader(beanFactory);
    int beanDefinitionCountBefore = beanFactory.getBeanDefinitionCount();
    // 注册当前类(非 @Component class)
    beanDefinitionReader.register(AnnotatedBeanDefinitionParsingDemo.class);
    int beanDefinitionCountAfter = beanFactory.getBeanDefinitionCount();
    int beanDefinitionCount = beanDefinitionCountAfter - beanDefinitionCountBefore;
    System.out.println("已加载 BeanDefinition 数量:" + beanDefinitionCount);
    // 普通的 Class 作为 Component 注册到 Spring IoC 容器后,通常 Bean 名称为 annotatedBeanDefinitionParsingDemo
    // Bean 名称生成来自于 BeanNameGenerator,注解实现 AnnotationBeanNameGenerator
    AnnotatedBeanDefinitionParsingDemo demo = beanFactory.getBean("annotatedBeanDefinitionParsingDemo",
            AnnotatedBeanDefinitionParsingDemo.class);
    System.out.println(demo);
}

注册的类并不一定非要标注@Component
AnnotatedBeanDefinitionReader并未实现BeanDefinitionReader.因为他不知道通过其他资源读取,直接通过register方法进行注册.

Spring Bean 注册阶段:BeanDefinition与单体Bean注册

第九章:Spring Bean生命周期(Bean Lifecycle)_第3张图片

org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition
在这个方法中有最中有最重要的2个属性beanDefinitionMap和beanDefinitionNames
beanDefinitionMap:用户保存beanDefinition的实例对象
beanDefinitionNames:用户保存注册进beanDefinitionMap的顺序

	synchronized (this.beanDefinitionMap) {
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					removeManualSingletonName(beanName);
				}

这里的updatedDefinitions 是非线程安全的,可以减少一些线程重进入的计算。

Spring BeanDefinition合并阶段:BeanDefinition合并过程是怎样出现的?

第九章:Spring Bean生命周期(Bean Lifecycle)_第4张图片

public class MergedBeanDefinitionDemo {

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 基于 XML 资源 BeanDefinitionReader 实现
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        String location = "META-INF/dependency-lookup-context.xml";
        // 基于 ClassPath 加载 XML 资源
        Resource resource = new ClassPathResource(location);
        // 指定字符编码 UTF-8
        EncodedResource encodedResource = new EncodedResource(resource, "UTF-8");
        int beanNumbers = beanDefinitionReader.loadBeanDefinitions(encodedResource);
        System.out.println("已加载 BeanDefinition 数量:" + beanNumbers);
        // 通过 Bean Id 和类型进行依赖查找
        User user = beanFactory.getBean("user", User.class);
        System.out.println(user);

        User superUser = beanFactory.getBean("superUser", User.class);
        System.out.println(superUser);
    }
}

Root BeanDefinition 不需要合并,不存在 parent
普通 beanDefinition GenericBeanDefinition 合并后 GenericBeanDefinition 变成 RootBeanDefinition,并且覆盖 parent 相关配置

Spring Bean Class加载阶段:Bean ClassLoader能够被替换吗?

第九章:Spring Bean生命周期(Bean Lifecycle)_第5张图片
总结 AbstractBeanFactory#resolveBeanClass中将string类型的beanClass 通过当前线程Thread.currentThread().getContextClassLoader(),Class.forName来获取class对象,将beanClass变为Class类型对象

Spring Bean实例化前阶段:Bean的实例化能否被绕开?第九章:Spring Bean生命周期(Bean Lifecycle)_第6张图片

最终是采用反射的newInstance实例化的,

Spring Bean实例化阶段:Bean实例是通过Java反射创建吗?

第九章:Spring Bean生命周期(Bean Lifecycle)_第7张图片

class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
        if (ObjectUtils.nullSafeEquals("superUser", beanName) && SuperUser.class.equals(beanClass)) {
            // 把配置完成 superUser Bean 覆盖
            return new SuperUser();
        }
        return null; // 保持 Spring IoC 容器的实例化操作
    }

    
}

最后的结论构造器注入时按照类型注入存在点歧义,应该是先按照类型在按照名称;当superUser的primary给去掉时,此时根据User类型查找时会找到两个匹配的bean对象,user和superUser在选择候选bean时是按照 primary bean->resolveDependency包含->beanName和descriptor.getDependencyName()相等的bean,当无primary bean是选择则是从user和superUser中选择的user,因为user bean的名称和userHolder注入的user名称相等

Spring Bean实例化后阶段:Bean实例化后是否一定被是使用吗?

第九章:Spring Bean生命周期(Bean Lifecycle)_第8张图片

class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
  @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (ObjectUtils.nullSafeEquals("user", beanName) && User.class.equals(bean.getClass())) {
            User user = (User) bean;
            user.setId(2L);
            user.setName("mercyblitz");
            // "user" 对象不允许属性赋值(填入)(配置元信息 -> 属性值)
            return false;
        }
        return true;
    }    
}

在bean实例化之后可以通过InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation设置Bean中的初始值并返回

Spring Bean属性赋值前阶段:配置后的PropertyValues还有机会修改吗?第九章:Spring Bean生命周期(Bean Lifecycle)_第9张图片

总结InstantiationAwareBeanPostProcessor方法:
postProcessBeforeInstantiation()在bean实例化前回调,返回实例则不对bean实例化,返回null则进行spring bean实例化(doCreateBean);
postProcessAfterInstantiation()在bean实例化后在填充bean属性之前回调,返回true则进行下一步的属性填充,返回false:则不进行属性填充
postProcessProperties在属性赋值前的回调在applyPropertyValues之前操作可以对属性添加或修改等操作最后在通过applyPropertyValues应用bean对应的wapper对象

Aware接口回调阶段:众多Aware接口回调的顺序是安排的?

第九章:Spring Bean生命周期(Bean Lifecycle)_第10张图片
在执行完org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean方法填充完属性后,在initializeBean中调用invokeAwareMethods

if (bean instanceof Aware) {
			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);
			}
		}

此处会执行 BeanNameAware,BeanClassLoaderAware,BeanFactoryAware三个接口的方法.如果只是普通的BeanFactory只支持这3个aware接口.
后面其他的aware是数据ApplicationContext生命周期里面的…
在applicationContext中的refresh()方法中->prepareBeanFactory()->

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));


ApplicationContextAwareProcessor 中实现的aware
private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof EnvironmentAware) {
			((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
		}
		if (bean instanceof EmbeddedValueResolverAware) {
			((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
		}
		if (bean instanceof ResourceLoaderAware) {
			((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
		}
		if (bean instanceof ApplicationEventPublisherAware) {
			((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
		}
		if (bean instanceof MessageSourceAware) {
			((MessageSourceAware) bean).setMessageSource(this.applicationContext);
		}
		if (bean instanceof ApplicationContextAware) {
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		}
	}

由于ApplicationContextAwareProcessor是一个内置类的关系,在ApplicationContext初始化的时候会动态的添加一个BeanPostProcessor(ApplicationContextAwareProcessor).
由此可见对于Aware接口的支持也是一个BeanFactory和ApplicationContext的区别.
BeanFactory只支持BeanNameAware,BeanClassLoaderAware,BeanFactoryAware 3个.
ApplicationContext支持多有的Aware.

Spring Bean初始化前阶段:BeanPostProcessor

第九章:Spring Bean生命周期(Bean Lifecycle)_第11张图片

通过XmlBeanDefinitionReader loadBeanDefinitions是将xml中bean对应的beanDefinition注册到beanFactory中,底层通过BeanDefinitionReaderUtils#registerBeanDefinition()方法实现,这个在BeanDefinition注册阶段讲过,这个时候只是注册beanDefinition没有像ApplicationContext.refresh()中的registerBeanPostProcessors()将bean post Processor添加到beanFactory的beanPostProcessors list集合中操作,所以xml读取的时候需要手动的addBeanPostProcessor;如果通过ClassPathXmlApplicationContext创建ApplicationContext的方式xml中定义MyInstantiationAwareBeanPostProcessor是可以的,因为ClassPathXmlApplicationContext创建时会执行refresh()操作会从beanFactory中找到MyInstantiationAwareBeanPostProcessor bean后添加到beanPostProcessors的list集合中

Spring Bean初始化阶段:@PostConstruct、InitializingBean以及自定义方法第九章:Spring Bean生命周期(Bean Lifecycle)_第12张图片

1.在bean初始化前阶段initializeBean()对应的applyBeanPostProcessorsBeforeInitialization()方法中执行完自定义的MyInstantiationAwareBeanPostProcessor的postProcessBeforeInitialization()方法同时会执行CommonAnnotationBeanPostProcessor的postProcessBeforeInitialization方法最后执行@PostConstruct修饰的initPostConstructor方法
2.其他两种bean初始化在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods()中被调用

Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
		// 调用CommonAnnotationBeanPostProcessor的postProcessBeforeInitialization完成@PostConstruct方法
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
		// 实现 afterPropertiesSet 和 自定义初始化方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}


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) () -> {
					// 调用afterPropertiesSet 方法
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				((InitializingBean) bean).afterPropertiesSet();
			}
		}

		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);
			}
		}

Spring Bean初始化后阶段:BeanPostProcessor第九章:Spring Bean生命周期(Bean Lifecycle)_第13张图片

在填充bean属性完成之后initializeBean()中有四个过程
1.aware的接口回调(不包括ApplicationContext相关)
2.postProcessBeforeInitialization()包括两部分关于ApplicationContextAwareProcessor的aware接口回调和自定义bean post processor的postProcessBeforeInitialization回调和@PostConstruct标识方法(CommonAnnotationBeanPostProcessor中)
3.invokeInitMethods() bean初始化的回调比如实现InitializingBean接口
4.applyBeanPostProcessorsAfterInitialization() bean初始化之后的回调

Spring Bean初始化完成阶段:SmartInitializingSingleton第九章:Spring Bean生命周期(Bean Lifecycle)_第14张图片

ApplicationContext在refresh的操作里等beanFactory的一系列操作,messageSource,注册listener等操作都完毕之后通过finishBeanFactoryInitialization开始实例化所有非懒加载的单例bean,具体是在finishBeanFactoryInitialization调用beanFactory#preInstantiateSingletons进行的,preInstantiateSingletons里面就是通过beanDefinitionNames循环调用getBean来实例化bean的,这里有个细节,beanDefinitionNames是拷贝到一个副本中,循环副本,使得还能注册新的beanDefinition.
getBean的操作就是我们之前那么多节课分析的一顿操作的过程,最终得到一个完整的状态的bean。 然后所有的非延迟单例都加载完毕之后,再重新循环副本,判断bean是否是SmartInitializingSingleton,如果是的话执行SmartInitializingSingleton#afterSingletonsInstantiated。这保证执行afterSingletonsInstantiated的时候的bean一定是完整的。

Spring Bean销毁前阶段:DestructionAwareBeanPostProcessor用在怎样的场景?

第九章:Spring Bean生命周期(Bean Lifecycle)_第15张图片
destroyBean 操作仅是触发 Bean 销毁生命周期,因为 Bean 有可能再次被初始化,比如显示地调用 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.Object, java.lang.String) 方法

Spring Bean销毁阶段:@PreDestroy、DisposableBean以及自定义方法

第九章:Spring Bean生命周期(Bean Lifecycle)_第16张图片
其中@PreDestory是在CommonAnnotationBeanPostProcessor中处理的.处于最先的阶段.

Spring Bean垃圾收集(GC):何时需要GC Spring Bean?第九章:Spring Bean生命周期(Bean Lifecycle)_第17张图片

面试题

第九章:Spring Bean生命周期(Bean Lifecycle)_第18张图片
第九章:Spring Bean生命周期(Bean Lifecycle)_第19张图片
第九章:Spring Bean生命周期(Bean Lifecycle)_第20张图片
总结:beanFactory处理bean的过程
1.注册bean Definition registerBeanDefinition()
2.bean Definition的合并阶段 getMergedLocalBeanDefinition(),比如user和superUser 最后都变为root bean Definition
3.创建bean createBean()
4.将bean类型从string变为class类型 resolveBeanClass()
5.bean实例化前工作resolveBeforeInstantiation(),比如可以返回自定义的bean对象让spring不在实例化bean对象
6.开始实例化bean doCreateBean()
7.实例化bean createBeanInstance()
8.bean实例化后 postProcessAfterInstantiation()返回false即bean不在对属性处理
9.属性赋值前对属性处理postProcessProperties()
10.属性赋值applyPropertyValues()
11.bean初始化阶段initializeBean()
12.初始化前aware接口回调(非ApplicationContextAware),比如beanFactoryAware
13.初始化前回调applyBeanPostProcessorsBeforeInitialization(),比如@PostConstructor
14.初始化invokeInitMethods(),比如实现InitializingBean接口的afterPropertiesSet()方法回调
15.初始化后的回调applyBeanPostProcessorsAfterInitialization()
16.bean重新的填充覆盖来更新bean preInstantiateSingletons()
17.bean销毁前postProcessBeforeDestruction()
18.bean销毁,比如@PreDestroy

你可能感兴趣的:(Spring核心编程思想)