Spring Bean作用域与生命周期

作用域

singleton:单例Bean只在容器中存在一个实例,在Spring内部通过HashMap来维护单例bean的缓存

prototype:每次索取bean时都会创建一个全新的Bean

request:每次请求都会创建一个全新Bean,该类型作用于Web类型的Spring容器

session:每个会话创建一个全新Bean,该类型作用于Web类型的Spring容器

globalSession:类似于session作用域,只是其用于portlet环境的web应用。如果在非portlet环境将视为session作用域

总结:以上就是spring中bean的作用域,其中singleton,prototype属于Spring bean的基本作作用域,request,session,globalSession属于web应用环境的作用域,必须有web应用环境的支持


生命周期

// AbstractAutowireCapableBeanFactory.java
	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
		BeanWrapper instanceWrapper = null;
		// 1.实例化Bean
		if (instanceWrapper == null) {
			instanceWrapper = this.createBeanInstance(beanName, mbd, args);
		}
		Object exposedObject = bean;
		// 2.属性赋值
		this.populateBean(beanName, mbd, instanceWrapper);
        // 3.初始化
		exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        // 4.销毁-注册回调接口
		this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
		return exposedObject;
	}
复制代码

Bean 的生命周期概括起来就是 4 个阶段

  1. 实例化(Instantiation)(第1步,实例化一个bean对象)
  2. 属性赋值(Populate)(第2步,为bean对象设置相关属性和依赖)
  3. 初始化(Initialization)(第 3~7 步,步骤较多,其中第 5、6 步为初始化操作,第 3、4 步为在初始化前执行,第 7 步在初始化后执行,该阶段结束,才能被用户使用)
    • 检查Aware相关接口并设置依赖
    • BeanPostProcessor前置处理
    • 若实现了InitializingBean接口,则调用该接口的AfterPropertiesSet()方法
    • 若配置了自定义的 init-method方法,则执行该方法
    • BeanPostProcessor后置处理
// AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    	// 检查Aware相关接口并设置依赖
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged(() -> {
				this.invokeAwareMethods(beanName, bean);
				return null;
			}, this.getAccessControlContext());
		} else {
			this.invokeAwareMethods(beanName, bean);
		}
		// BeanPostProcessor前置处理
		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
		}
	
		try {
            // 若实现了InitializingBean接口,则调用该接口的AfterPropertiesSet()方法
            // 若配置了自定义的 init-method方法,则执行init-method方法
			this.invokeInitMethods(beanName, wrappedBean, mbd);
		} catch (Throwable var6) {
			throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
		}

		if (mbd == null || !mbd.isSynthetic()) {
            // BeanPostProcessor后置处理
			wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}
复制代码
  1. 销毁( 8~10步,第8步不是真正意义上的销毁(还没使用呢),而是先在使用前注册了销毁的相关调用接口,为了后面第9、10步真正销毁 bean 时再执行相应的方法 )
    • 注册Destruction相关回调接口 (不是真正意义上的销毁(还没使用呢))
    • 是否实现DisposableBean接口
    • 是否配置自定义的destory-method (和初始化过程很像,都是检查是否实现接口和配置方法)
public void destroy() {
        // 9. 若实现 DisposableBean 接口,则执行 destory()方法
		if (this.invokeDisposableBean) {
			if (logger.isTraceEnabled()) {
				logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
			}
			try {
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged(() -> {
						((DisposableBean) this.bean).destroy();
						return null;
					}, this.acc);
				} else {
					((DisposableBean) this.bean).destroy();
				}
			}
		}
    	// 10. 若配置自定义的 detory-method 方法,则执行
		if (this.destroyMethod != null) {
			this.invokeCustomDestroyMethod(this.destroyMethod);
		} else if (this.destroyMethodName != null) {
			Method methodToInvoke = this.determineDestroyMethod(this.destroyMethodName);
			if (methodToInvoke != null) {
				this.invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
			}
		}
	}
复制代码

扩展点的作用

部分内容转载:mp.weixin.qq.com/s/20QLBE6Cr…