• 【spring mvc】application context中【bean】的生命周期


    • 生命周期过程

    主要分为四部分:

    一、实例化

    1. 当调用者通过 getBean( name )向 容器寻找Bean 时,如果容器注册了org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口,在实例 bean 之前,将调用该接口的 postProcessBeforeInstantiation ()方法。
    2. 根据配置情况调用 Bean构造函数或工厂方法实例化 bean。
    3. 如果容器注册了 org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口,在实例 bean 之后,调用该接口的 postProcessAfterInstantiation ()方法,可以在这里对已经实例化的对象进行一些装饰。
    4. 受用依赖注入,Spring 按照 Bean 定义信息配置 Bean 的所有属性 ,在设置每个属性之前将调用InstantiationAwareBeanPostProcess接口的 postProcessPropertyValues ()方法 。
    5 .如果Bean实现了BeanNameAware接口,会回调该接口的setBeanName()方法,传入该Bean的id,此时该Bean就获得了自己在配置文件中的id。
    6 .如果Bean实现了BeanFactoryAware接口,会回调该接口的setBeanFactory()方法,传入该Bean的BeanFactory,这样该Bean就获得了自己所在的BeanFactory。
    7、如果Bean实现了ApplicationContextAware接口,会回调该接口的setApplicationContext()方法,传入该Bean的ApplicationContext,这样该Bean就获得了自己所在的ApplicationContext。

    二、初始化

    8.如果有Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessBeforeInitialzation()方法对 bean进行加工操作,这个非常重要, spring 的 AOP 就是用它实现的

    9.如果Bean实现了InitializingBean接口,则会回调该接口的afterPropertiesSet()方法,实现 InitializingBean接口必须实现afterPropertiesSet方法。(这个方法的作用是啥,还不太清楚)

    10.如果Bean配置了init-method方法,则会执行init-method配置的方法。

    11.如果有Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessAfterInitialization()方法。

    三、执行具体的操作

    12.经过流程9之后,就可以正式使用该Bean了,对于scope为singleton的Bean,Spring的ioc容器中会缓存一份该bean的实例,而对于scope为prototype的Bean,每次被调用都会new一个新的对象,期生命周期就交给调用方管理了,不再是Spring容器进行管理了。

    然后就可以用这个Bean想干啥干啥了。。。

    四、销毁

    13.容器关闭后,如果Bean实现了DisposableBean接口,则会回调该接口的destroy()方法。

    14.如果Bean配置了destroy-method方法,则会执行destroy-method配置的方法,至此,整个Bean的生命周期结束。

    • 代码解析

    示例代码地址:https://github.com/handv/SpringMVCDemo/tree/master/SpringMVC_000

    代码执行结果:

    开始初始化容器
    九月 25, 2016 10:44:50 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@b4aa453: startup date [Sun Sep 25 22:44:50 CST 2016]; root of context hierarchy
    九月 25, 2016 10:44:50 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [com/test/spring/life/applicationContext.xml]
    Person类构造方法
    set方法被调用
    setBeanName被调用,beanName:person1
    setBeanFactory被调用,beanFactory
    setApplicationContext被调用
    postProcessBeforeInitialization被调用
    afterPropertiesSet被调用
    myInit被调用
    postProcessAfterInitialization被调用
    xml加载完毕
    name is :jack
    关闭容器
    九月 25, 2016 10:44:51 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
    信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@b4aa453: startup date [Sun Sep 25 22:44:50 CST 2016]; root of context hierarchy
    destory被调用
    myDestroy被调用

    1、AbstractAutowireCapableBeanFactory.populateBean

    protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    	...
    
    	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    		for (BeanPostProcessor bp : getBeanPostProcessors()) {
    		//这里用到了InstantiationAwareBeanPostProcessor
    			if (bp instanceof InstantiationAwareBeanPostProcessor) {
    				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    		//这里用到了postProcessAfterInstantiation方法
    				if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    					continueWithPropertyPopulation = false;
    					break;
    				}
    			}
    		}
    	}
    
    	...
    	
    	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    	boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
    
    	if (hasInstAwareBpps || needsDepCheck) {
    		PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    		if (hasInstAwareBpps) {
    			for (BeanPostProcessor bp : getBeanPostProcessors()) {
    		//注册InstantiationAwareBeanPostProcessor接口
    				if (bp instanceof InstantiationAwareBeanPostProcessor) {
    					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    		//调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法
    					pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
    					if (pvs == null) {
    						return;
    					}
    				}
    			}
    		}
    		if (needsDepCheck) {
    			checkDependencies(beanName, mbd, filteredPds, pvs);
    		}
    	}
        //该处反射执行Bean的setxxx方法
    	applyPropertyValues(beanName, mbd, bw, pvs);
    }

    2、AbstractAutowireCapableBeanFactory.invokeAwareMethods()

    private void invokeAwareMethods(final String beanName, final Object bean) {
    		if (bean instanceof Aware) {
    			if (bean instanceof BeanNameAware) {
    			//设置BeanName
    				((BeanNameAware) bean).setBeanName(beanName);
    			}
    			if (bean instanceof BeanClassLoaderAware) {
    				((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
    			}
    			if (bean instanceof BeanFactoryAware) {
    			//设置BeanFactory
    				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    			}
    		}
    	}

    3、AbstractAutowireCapableBeanFactory.initializeBean

    /**
    	 * Initialize the given bean instance, applying factory callbacks
    	 * as well as init methods and bean post processors.
    	 * <p>Called from {@link #createBean} for traditionally defined beans,
    	 * and from {@link #initializeBean} for existing bean instances.
    	 * @param beanName the bean name in the factory (for debugging purposes)
    	 * @param bean the new bean instance we may need to initialize
    	 * @param mbd the bean definition that the bean was created with
    	 * (can also be {@code null}, if given an existing bean instance)
    	 * @return the initialized bean instance (potentially wrapped)
    	 * @see BeanNameAware
    	 * @see BeanClassLoaderAware
    	 * @see BeanFactoryAware
    	 * @see #applyBeanPostProcessorsBeforeInitialization
    	 * @see #invokeInitMethods
    	 * @see #applyBeanPostProcessorsAfterInitialization
    	 */
    	protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    		if (System.getSecurityManager() != null) {
    			AccessController.doPrivileged(new PrivilegedAction<Object>() {
    				@Override
    				public Object run() {
    					invokeAwareMethods(beanName, bean);
    					return null;
    				}
    			}, getAccessControlContext());
    		}
    		else {
    			invokeAwareMethods(beanName, bean);
    		}
    
    		Object wrappedBean = bean;
    		if (mbd == null || !mbd.isSynthetic()) {
    			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    		}
    
    		try {
    			invokeInitMethods(beanName, wrappedBean, mbd);
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(
    					(mbd != null ? mbd.getResourceDescription() : null),
    					beanName, "Invocation of init method failed", ex);
    		}
    
    		if (mbd == null || !mbd.isSynthetic()) {
    			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    		}
    		return wrappedBean;
    	}

    后续代码可以看源码的注释,先不看了,太多了

    参考:http://www.jianshu.com/p/3944792a5fff

  • 相关阅读:
    软件需求阅读笔记二
    寒假小程序开发记录2
    软件需求阅读笔记一
    寒假小程序开发记录1
    软件工程概论课个人总结
    06大道至简阅读笔记
    golang算法——leetcode-46
    实验 5 Spark SQL 编程初级实践
    scala链接数据库Exception in thread "main" java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
    Error:(15, 103) value toDF is not a member of org.apache.spark.rdd.RDD[Employee] .map(attributes => Employee(attributes(0).trim.toInt, attributes(1), attributes(2).trim.toInt)).toDF()
  • 原文地址:https://www.cnblogs.com/hantalk/p/6644701.html
Copyright © 2020-2023  润新知