剑指Spring源码(三)俯瞰Spring的Bean的生命周期(大众版)

栏目: Java · 发布时间: 7年前

内容简介:距离上一次写Spring源码解析,已经过去了快要好几个月了,主要原因还是Spring的源码解析类文章太难写了,不像我先前写的什么CAS源码,AQS源码,LinkedBlockingQueue等等,这些无非就是分析几个核心方法,代码也不算太长,就像比较复杂的AQS源码也是两篇搞定的,虽然AQS源码也很多东西也不能算是百分百的理解,但是核心思想应该是还算理解的。解析完毕成就感也满满的,写完博客,看着大段大段的文字,心里也很开心:哈哈哈,原来JDK源码也是可以读懂的,而且还能写出来。但是Spring源码就不一样了

距离上一次写Spring源码解析,已经过去了快要好几个月了,主要原因还是Spring的源码解析类文章太难写了,不像我先前写的什么CAS源码,AQS源码,LinkedBlockingQueue等等,这些无非就是分析几个核心方法,代码也不算太长,就像比较复杂的AQS源码也是两篇搞定的,虽然AQS源码也很多东西也不能算是百分百的理解,但是核心思想应该是还算理解的。解析完毕成就感也满满的,写完博客,看着大段大段的文字,心里也很开心:哈哈哈,原来JDK源码也是可以读懂的,而且还能写出来。但是Spring源码就不一样了,如果和先前的源码分析类文章一样逐行去解析的话,那么可能一篇博客写下来,一个小小小小小方法都没法分析完,就算分析完毕了,也突出不了重点啊,但是Spring源码解析还是要继续的,就当做是自己的学习笔记把。

今天我们要看的内容是Spring Bean的生命周期,当然本篇博客只是带着大家俯瞰下,不会进行过多的源码分析,甚至只是贴下代码,不做分析,只是找到Spring Bean生命周期的回调或者钩子,当然这可能只是我的个人理解,大家还是要以怀疑的目光看待,也许我分析的是有问题的。

不知道Spring官方对Bean的生命问题是否有明确的定义或者解析,但是Spring In Action以及市面上流传的大部分博客是这样的:

  1. 实例化Bean对象,这个时候Bean的对象是非常低级的,基本不能够被我们使用,因为连最基本的属性都没有设置,可以理解为连Autowired注解都是没有解析的;
  2. 填充属性,当做完这一步,Bean对象基本是完整的了,可以理解为Autowired注解已经解析完毕,依赖注入完成了;
  3. 如果Bean实现了BeanNameAware接口,则调用setBeanName方法;
  4. 如果Bean实现了BeanClassLoaderAware接口,则调用BeanClassLoaderAware方法;
  5. 如果Bean实现了BeanFactoryAware接口,则调用setBeanFactory方法;
  6. 调用BeanPostProcessor的postProcessBeforeInitialization方法;
  7. 如果Bean实现了InitializingBean接口,调用afterPropertiesSet方法;
  8. 如果Bean定义了init-method方法,则调用Bean的init-method方法;
  9. 调用BeanPostProcessor的postProcessBeforeInitialization方法;当进行到这一步,Bean已经被准备就绪了,一直停留在应用的上下文中,直到被销毁;
  10. 如果应用的上下文被销毁了,如果Bean实现了DisposableBean接口,则调用destroy方法,如果Bean定义了destory-method声明了销毁方法也会被调用。

为了验证上面的逻辑,可以做个试验:

首先定义了一个Bean,里面有各种回调和钩子,其中需要注意下,我在SpringBean的构造方法中打印了studentService,看SpringBean被new的出来的时候,studentService是否被注入了;又在setBeanName中打印了studentService,看此时studentService是否被注入了,以此来验证,Bean是何时完成的自动注入的(这个StudentServiceImpl 类的代码就不贴出来了,无非就是一个最普通的Bean):

public class SpringBean implements InitializingBean, DisposableBean, BeanNameAware, BeanFactoryAware, BeanClassLoaderAware {

	public SpringBean() {
		System.out.println("SpringBean构造方法:" + studentService);
		System.out.println("SpringBean构造方法");
	}

	@Autowired
	StudentServiceImpl studentService;

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("afterPropertiesSet");
	}

	@Override
	public void destroy() throws Exception {
		System.out.println("destroy");
	}

	@Override
	public void setBeanClassLoader(ClassLoader classLoader) {
		System.out.println("setBeanClassLoader");
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		System.out.println("setBeanFactory");
	}

	@Override
	public void setBeanName(String name) {
		System.out.println("setBeanName:" + studentService);
		System.out.println("setBeanName");
	}

	public void initMethod() {
		System.out.println("initMethod");
	}

	public void destroyMethod() {
		System.out.println("destroyMethod");
	}
}

复制代码

再定义一个BeanPostProcessor,在重写的两个方法中进行了判断,如果传进来的beanName是springBean才进行打印:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if(beanName.equals("springBean")) {
			System.out.println("postProcessBeforeInitialization");
		}
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if(beanName.equals("springBean")) {
			System.out.println("postProcessAfterInitialization");
		}
		return bean;
	}
}
复制代码

定义一个配置类,完成自动扫描,但是SpringBean是手动注册的,并且声明了initMethod和destroyMethod:

@Configuration
@ComponentScan
public class AppConfig {
	@Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
	public SpringBean springBean() {
		return new SpringBean();
	}
}
复制代码

最后就是启动类了:

public static void main(String[] args) {
		AnnotationConfigApplicationContext annotationConfigApplicationContext =
				new AnnotationConfigApplicationContext(AppConfig.class);
		annotationConfigApplicationContext.destroy();
	}
复制代码

运行结果:

SpringBean构造方法:null
SpringBean构造方法
setBeanName:com.codebear.StudentServiceImpl@31190526
setBeanName
setBeanClassLoader
setBeanFactory
postProcessBeforeInitialization
afterPropertiesSet
initMethod
postProcessAfterInitialization
destroy
destroyMethod
复制代码

可以看到,试验结果和上面分析的完全一致。

这就是广为流传的Spring生命周期。

也许你在应付面试的时候,是死记硬背这些结论的,现在我带着你找到这些方法,跟我来。

首先我们来到AnnotationConfigApplicationContext的构造方法:

//根据参数类型可以知道,其实可以传入多个annotatedClasses,但是这种情况出现的比较少
	public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
		//调用无参构造函数,会先调用父类GenericApplicationContext的构造函数
		//父类的构造函数里面就是初始化DefaultListableBeanFactory,并且赋值给beanFactory
		//本类的构造函数里面,初始化了一个读取器:AnnotatedBeanDefinitionReader read,一个扫描器ClassPathBeanDefinitionScanner scanner
		//scanner的用处不是很大,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的
		this();
		//把传入的类进行注册,这里有两个情况,
		//传入传统的配置类
		//传入bean(虽然一般没有人会这么做
		//看到后面会知道spring把传统的带上@Configuration的配置类称之为FULL配置类,不带@Configuration的称之为Lite配置类
		//但是我们这里先把带上@Configuration的配置类称之为传统配置类,不带的称之为普通bean
		register(annotatedClasses);
		//刷新
		refresh();
	}
复制代码

进入refresh方法,refresh方法中有一个finishBeanFactoryInitialization小方法,这个方法是用来实例化懒加载单例Bean的,也就是我们的Bean都是在这里被创建出来的(当然我这里说的的是绝大部分情况是这样的):

finishBeanFactoryInitialization(beanFactory);
复制代码

我们再进入finishBeanFactoryInitialization这方法,里面有一个beanFactory.preInstantiateSingletons()方法:

//初始化所有的非懒加载单例
		beanFactory.preInstantiateSingletons();
复制代码

我们尝试再点进去,这个时候你会发现这是一个接口,好在它只有一个实现类,所以可以我们来到了他的唯一实现,实现类就是org.springframework.beans.factory.support.DefaultListableBeanFactory,这里面是一个循环,我们的Bean就是循环被创建出来的,我们找到其中的getBean方法:

getBean(beanName);
复制代码

这里有一个分支,如果Bean是FactoryBean,如何如何,如果Bean不是FactoryBean如何如何,好在不管是不是FactoryBean,最终还是会调用getBean方法,所以我们可以毫不犹豫的点进去,点进去之后,你会发现,这是一个门面方法,直接调用了doGetBean方法:

return doGetBean(name, null, null, false);
复制代码

再进去,不断的深入,接近我们要寻找的东西。 这里面的比较复杂,但是有我在,我可以直接告诉你,下一步我们要进入哪里,我们要进入

if (mbd.isSingleton()) {

					//getSingleton中的第二个参数类型是ObjectFactory<?>,是一个函数式接口,不会立刻执行,而是在
					//getSingleton方法中,调用ObjectFactory的getObject,才会执行createBean
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
复制代码

这里面的createBean方法,再点进去啊,但是又点不进去了,这是接口啊,但是别慌,这个接口又只有一个实现类,所以说 没事,就是干,这个实现类为org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory。

这个实现的方法里面又做了很多事情,我们就不去看了,我就是带着大家找到那几个生命周期的回调到底定义在哪里就OK了。

Object beanInstance = doCreateBean(beanName, mbdToUse, args);//创建bean,核心
			if (logger.isDebugEnabled()) {
				logger.debug("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
复制代码

再继续深入doCreateBean方法,这个方法又做了一堆一堆的事情,但是值得开心的事情就是 我们已经找到了我们要寻找的东西了。

创建实例

首先是创建实例,位于:

instanceWrapper = createBeanInstance(beanName, mbd, args);//创建bean的实例。核心
复制代码

填充属性

其次是填充属性,位于:

populateBean(beanName, mbd, instanceWrapper);//填充属性,炒鸡重要
复制代码

在填充属性下面有一行代码:

exposedObject = initializeBean(beanName, exposedObject, mbd);
复制代码

继续深入进去。

aware系列接口的回调

aware系列接口的回调位于initializeBean中的invokeAwareMethods方法:

invokeAwareMethods(beanName, bean);
复制代码
private void invokeAwareMethods(final String beanName, final Object bean) {
		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);
			}
		}
	}
复制代码

BeanPostProcessor的postProcessBeforeInitialization方法

BeanPostProcessor的postProcessBeforeInitialization方法位于initializeBean的

if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}
复制代码
@Override
	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;
	}
复制代码

afterPropertiesSet init-method

afterPropertiesSet init-method位于initializeBean中的

invokeInitMethods(beanName, wrappedBean, mbd);
复制代码

这里面调用了两个方法,一个是afterPropertiesSet方法,一个是init-method方法:

((InitializingBean) bean).afterPropertiesSet();
复制代码
invokeCustomInitMethod(beanName, bean, mbd);
复制代码

BeanPostProcessor的postProcessAfterInitialization方法

BeanPostProcessor的postProcessAfterInitialization方法位于initializeBean的

if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
复制代码
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}
复制代码

当然在实际的开发中,应该没人会去销毁Spring的应用上下文把,所以剩余的两个销毁的回调就不去找了。

这就是广为流传的Spring Bean的生命周期,我也带着大家找到了各种回调和钩子,但是我认为这并非是Spring Bean完整的生命周期,只是经过简化的,那么我认为的完整的生命周期是如何的呢,请听下回分解。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Linux Device Drivers

Linux Device Drivers

Jonathan Corbet、Alessandro Rubini、Greg Kroah-Hartman / O'Reilly Media / 2005-2-17 / USD 39.95

Device drivers literally drive everything you're interested in--disks, monitors, keyboards, modems--everything outside the computer chip and memory. And writing device drivers is one of the few areas ......一起来看看 《Linux Device Drivers》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

在线进制转换器
在线进制转换器

各进制数互转换器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具