Bean在Spring中的生命周期

Bean生命周期示意图

在这里插入图片描述
接下来我们通过源码 + 实现代码的方式,看看bean各个阶段的生命周期的具体作用。

因为主要讲解得是bean在初始化完成之后的过程,也就不包括一堆前置处理,如:如何解决循环依赖,如何解析文件等内容。一切都是已经发生在构造完成之后发生的事情。

实例化Bean对象

BeanWrapper

在这里插入图片描述
在这里插入图片描述
从BeanWrapper继承ConfigurablePropertyAccessor(可配置属性访问),而ConfigurablePropertyAccessor又分配继承PropertyAccessor(属性访问),PropertyEditorRegistry(注册属性编辑器),TypeConverter(类型转换器)。就单单看中文,我们都已经可以猜出个大概。那BeanWrapper到底有什么功能。

BeanWrapper功能

Spring创建bean的过程也就是反射使用的过程,BeanWrapper其作用是对某个创建好初始化成功bean进行“包裹”,然后对这个“包裹”的bean进行相应属性的操作。先看看代码

public class CCN {
	private String name;

	@Override
	public String toString() {
		return "CCN{" +
				"name='" + name + '\'' +
				'}';
	}
	// 后加代码
		public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

基于JDK反射

	public class Reflect {
		public static void main(String[] args) throws Exception {
			Class<?> clz = Class.forName("beanwrapper.Reflect");
			CCN ccn = (CCN) clz.newInstance();
			Field name = clz.getField("name");
			name.setAccessible(true);
			name.set(ccn,"牛逼");
			System.out.println(ccn);
		}
	}

基于BeanWrapper

	public class BeanWrapper {
		public static void main(String[] args) throws Exception{
			Class<?> clz = Class.forName("beanwrapper.Reflect");
			CCN ccn = (CCN) clz.newInstance();
			BeanWrapperImpl bw = new BeanWrapperImpl(ccn);
			bw.setPropertyValue("name","牛逼O");
			ccn = (CCN) bw.getWrappedInstance();
			System.out.println(ccn);
		}
	}
	// Exception in thread "main" org.springframework.beans.NotWritablePropertyException: Invalid property 'name' of bean class [beanwrapper.CCN]: Bean property 'name' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?

报错原因BeanWrapper设计属性需要getset方式。给Person添加getset就可以了!

上述就是BeanWrapper,接下来到Spring如何使用BeanWrapper

设计属性

在这里插入图片描述

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		if (bw == null) {
			if (mbd.hasPropertyValues()) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
			}
			else {
				// Skip property population phase for null instance.
				return;
			}
		}

		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				// InstantiationAwareBeanPostProcessor 特别的实例化。不用普通属性的输入
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					// Perform operations after the bean has been instantiated, via a constructor or factory method,
					// 通过构造器和工厂方法构建的bean。是否需要特别处理
					// 我们知道构造器构建的 或者工厂方法构建的,有可能就没必要再注入属性了,也可能需要。所以在这里判断
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						return;
					}
				}
			}
		}

		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
		// xml对应bean 配置 autowire = “byType/byName”  看看注解的能否进来
		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			// 额外的属性注入 这也是Aware接口的作用
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						if (filteredPds == null) {
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
							return;
						}
					}
					pvs = pvsToUse;
				}
			}
		}
		if (needsDepCheck) {
			if (filteredPds == null) {
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		if (pvs != null) {
			// 处理属性注入
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

上述是Spring5.2X中populateBean的源码。可能你没有仔细看,毕竟源码还是需要自己慢慢看才行。其实也就做了几件事。

  1. 第一件事要不要注入属性
  2. 是否按照auto方式注入属性,是的话,就注入
  3. 是否实现了InstantiationAwareBeanPostProcessor接口实现额外的属性注入***
  4. 属性注入

这里属性注入如何实现代码就不点进去看了,有兴趣的同学可以仔细看看,其实也就是基于BeanWarpper。底层是反射的原理注入属性。

重点说说第三点InstantiationAwareBeanPostProcessor

在这里插入图片描述

在这里插入图片描述

InstantiationAwareBeanPostProcessor继承自BeanPostProcessor并扩展了BeanPostProcessor里面的方法

BeanPostProcessor接口中方法描述执行顺序
postProcessBeforeInitialization在Bean的自定义初始化方法之前执行5
postProcessAfterInitialization在Bean的自定义初始化方法执行完成之后执行4
-------------
InstantiationAwareBeanPostProcessor接口中方法描述
postProcessBeforeInstantiation在Bean的自定义构造方法之前执行,1
postProcessAfterInstantiation在Bean的自定义构造方法执行完成之后执行2
postProcessProperties对属性值进行修改,如果postProcessAfterInstantiation方法返回false,该方法可能不会被调用。可以在该方法内对属性值进行修改3
@Deprecated postProcessPropertyValues同上,被上面方法覆盖了3

英语时间

单词翻译含义状态
Instantiation实例化class.newInstance()。new 成功了 但是还没有开始赋值无 -》 有
Initialization初始化;构造过程开始给对象赋值的过程。有 - 》 完善
	public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

	/**
	 * BeanPostProcessor接口中的方法
	 * 在Bean的自定义初始化方法之前执行
	 * Bean对象已经存在了
	 */
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("postProcessBeforeInitialization4");
		return bean;
	}

	/**
	 * BeanPostProcessor接口中的方法
	 * 在Bean的自定义初始化方法执行完成之后执行
	 * Bean对象已经存在了
	 */
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("postProcessAfterInitialization5");
		return bean;
	}

	/**
	 * InstantiationAwareBeanPostProcessor中自定义的方法
	 * 在方法实例化之前执行  Bean对象还没有
	 */
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		System.out.println("postProcessBeforeInstantiation1");
		return null;
	}

	/**
	 * InstantiationAwareBeanPostProcessor中自定义的方法
	 * 在方法实例化之后执行  Bean对象已经创建出来了
	 */
	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		System.out.println("postProcessAfterInstantiation2");
		return true;
	}
		/**
	 * InstantiationAwareBeanPostProcessor中自定义的方法
	 * 可以用来修改Bean中属性的内容
	 */
	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
		System.out.println("postProcessProperties3");
		return pvs;
	}
}

在这里插入图片描述
如果你仔细看了吧,在第一个第一个执行的方法,也就是postProcessBeforeInstantiation。回调的参数是Class,后面都是 Object 类型。但是返回类型是Object。其实就是让你自己来创建对象。
在这里插入图片描述
整一个InstantiationAwareBeanPostProcessor 就是把整个原本让Spring帮我们做的过程,让你自己来完成了。就这么简单。这也是Spring留给我们的扩展。想改变参数属性输入。。。等等。让构建过程对于开发者可透明也可以不透明。

好,InstantiationAwareBeanPostProcessor和BeanPostProcessor。跟着源码脚步继续

过度

在这里插入图片描述

接着后续的生命周期,就是去exposedObject。扩展对象。那里面做了什么呢

在这里插入图片描述

整一个使用前的4的周期 都在一个initializeBean方法里面。接下来我们一个个看

检查Aware相关接口

有道翻译:aware意识到的;知道的;有…方面知识的;懂世故的
从字面意思上看就好像一些恍然大悟的感觉。造句:突然意识到。。。去到某事!。接来下我们看漫到底。。。去做了某事。
要明白一点这里的Aware跟上面所属的InstantiationAwareBeanPostProcessor不是同一种东西,但是意思就一样的也是意识到,去到某事。接下来我们看看相关Aware接口
在这里插入图片描述

	public class AwareBean  implements ApplicationContextAware, BeanNameAware {
		public String name;
		public ApplicationContext applicationContext;
		public String beanName;

		public void setName(String name) {
			this.name = name;
		}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

	@Override
	public void setBeanName(String name) {
		this.beanName = name;
	}
}

在这里插入图片描述

在这里插入图片描述
也就那样了。那么再看看有哪些可以通过Aware注入

接口作用
BeanNameAware注入beanName,如代码
BeanClassLoaderAware注入加载该bean对应的ClassLoader
BeanFactoryAware把管理Bean,创建Bean。大哥大Bean工厂注入
接口同一归类
以下接口都是基于ApplicationContext向上转型然后注入对应属性。
ResoucesLoaderAware读取配置文件工具
ApplicationExentPublisherAware处理事件
MessageSouceAware国际化的支持
ApplicationContextAwareApplicationContext本身

在这里插入图片描述

BeanPostProcessor前置处理

在InstantiationAwareBeanPostProcessor已经讲过了

就到了这一步,Aware也注入好属性了,整个对象就已经在完成的了。接下来你需要做啥补充就是在这里

InitializingBean

InitializingBean隐藏在 invokeInitMethods内部
在这里插入图片描述
在这里插入图片描述
从方法名字可以看出。属性设置之后你想做点什么?
我没试过,但是让我们现在想想,一般属性设置完成一周我们会做什么。在他还没有扩展,变成代理对象之前。
在这里插入图片描述
我看了一下实现他们的接口大多数都是做缓存的。特别看一下重点AbstractFactoryBean,他也实现了该接口。并重写了这个方法
在这里插入图片描述在这里插入图片描述
如果通过工厂bean构建的是一个单例,那么他就会创建事先创建一个单例bean对象。当要注入的时候注入这个对象。

这里留下一个疑问?既然事先就处理工厂bean生产的bean单例对象,那么如果该对象需要增强,为什么不保存增强后的对象呢?而是让该单例bean在注册的时候在增强。
我想这个目的单一职责问题。毕竟单例bean还是要注册的,只是它创建的方法不一样。他还是会走过这个流程。工厂bean只是节省了。创建的过程。

自定义init_method

在这里插入图片描述
在这里插入图片描述
上面代码,就是Spring会帮我们调用,配置好的initMethod方法,就这么简单。那么initMethod有什么用呢。可以做到类似Static静态代码框 包装代码的作用。但成员属性Static代码块可不能帮我们设置,所以Spring就提供了一种让可以第一时间调用的方法。从源码的角度还行init-method只能有一个。我们试试。
我原本还想写代码试一试,聪明的我发现。xml配置中只让我写一个。好吧!得到证实
在这里插入图片描述

BeanPostProcessor后置处理

在InstantiationAwareBeanPostProcessor已经讲过了

就到了这一步,init_method帮我们先调用了一些需要先初始化的方法,通过源码。我们知道Spring在这里帮助了我们实现AOP。那么其实我们也可以在这里实现自己的代理。一层套一层。代中代。AOP的细节我不在这里讲解。其实我也写关于AOP的文章。但是源码很长又有Cglib又有jdk动态代理的内容。等我抓出细节,再让该文章跟大伙见面。

Destruction相关回调接口

Destruction : 破坏,摧毁
这个我暂时没看到,莫非Spring5.2源码没有了相关的代码。一开始的图是来自Spring揭秘。2.多的一个执行流程图。有没有人告诉我,是不是删掉了,或者我到时候考究一下。

答案在下面

可使用ing

DisposableBean接口

disposable : 可任意处理的;可自由使用的;用完即可丢弃的
在这里插入图片描述
在这里插入图片描述

原来这三者结合到了一起,来控制除了prototype的摧毁方式。

destory方法

在这里插入图片描述

答案在上面

总结

InitializingBean和Init-method用于对象的自定义初始化相对应,DisposableBean和destory-method为对象提供了执行自定义销毁的机会。

Spring Bean生命周期到此结束。谢谢大家

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值