spring中Bean的生命周期

Posted Sup_Heaven

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring中Bean的生命周期相关的知识,希望对你有一定的参考价值。

Web容器Tomcat或Resin启动的时候会去加载web.xml。我们在web.xml中增加
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

或:
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>
org.
springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

那么Web容器会默认自动加载/WEB-INF/applicationContext.xml初始化,一般通过

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml</param-value>
</context-param>

去寻找类路径(一般我们设置为WebRoot/WEB-INF/classes)下面的applicationContext.xml

(1)Bean的建立:容器寻找Bean的定义信息并将其实例化。

(2)属性注入:使用依赖注入,Spring按照Bean定义信息配置Bean所有属性

(3)BeanNameAwaresetBeanName():如果Bean类有实现org.springframework.beans.BeanNameAware接口,工厂调用BeansetBeanName()方法传递BeanID

(4)BeanFactoryAwaresetBeanFactory():如果Bean类有实现org.springframework.beans.factory.BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。

(5)BeanPostProcessorsProcessBeforeInitialization():如果有org.springframework.beans.factory.config.BeanPostProcessorsBean关联,那么其postProcessBeforeInitialization()方法将被将被调用。

(6)initializingBeanafterPropertiesSet():如果Bean类已实现org.springframework.beans.factory.InitializingBean接口,则执行他的afterProPertiesSet()方法。

(7)Bean定义文件中定义init-method:可以在Bean定义文件中使用"init-method"属性设定方法名称例如。如果有以上设置的话,则执行到这个阶段,就会执行initBean()方法。

(8)BeanPostProcessorsProcessaAfterInitialization():如果有任何的BeanPostProcessors实例与Bean实例关联,则执行BeanPostProcessors实例的ProcessaAfterInitialization()方法。


此时,Bean已经可以被应用系统使用,并且将保留在BeanFactory中知道它不在被使用。有两种方法可以将其从BeanFactory中删除掉

1DisposableBeandestroy():在容器关闭时,如果Bean类有实现org.springframework.beans.factory.DisposableBean接口,则执行他的destroy()方法。

2Bean定义文件中定义destroy-method:在容器关闭时,可以在Bean定义文件中使用"destroy-method"属性设定方法名称。

如果有以上设定的话,则进行至这个阶段时,就会执行destroy()方法,如果是使用ApplicationContext来生成并管理Bean的话则稍有不同,使用ApplicationContext来生成及管理Bean实例的话,在执行BeanFactoryAwaresetBeanFactory()阶段后,若Bean类上有实现org.springframework.context.ApplicationContextAware接口,则执行其setApplicationContext()方法,接着才执行BeanPostProcessorsProcessBeforeInitialization()及之后的流程。



代码测试:

在applicationContext.xml中配置如下:

<bean id="teacher" class="com.lxq.test.Teacher" init-method="init"
		destroy-method="destroy">
		<constructor-arg type="java.lang.String" index="0">
			<value>default_xml_constructor</value>
		</constructor-arg>
		<property name="name">
			<value>default_xml_property</value>
		</property>
	</bean>

	<bean id="myBeanPostProcessor" class="com.lxq.test.MyBeanPostProcessor" >
	</bean>


Teacher类,继承一些接口:

package com.lxq.test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;

public class Teacher implements BeanFactoryAware, BeanNameAware,
		InitializingBean 
	private String name;
	private Integer age;
	
	private String beanName;
	private BeanFactory beanFactory;

	public void setName(String name) 
		System.out.println("这是在调用Teacher-setName,将名字由" + this.name + "设置为"
				+ name);
		this.name = name;
	

	public Teacher(String name) 
		System.out.println("这是在调用Teacher的构造方法,将名字由" + this.name + "设置为" + name);
	

	public void init() 
		this.name = "default_init";
		System.out.println("这是Teacher-init,将名字由" + this.name
				+ "设置为default_init");
	

	public void destroy() 
		System.out.println("这是Teacher-destroy");
	

	public void display() 
		System.out.println(this.name + "-" + this.age);
	

	public void afterPropertiesSet() throws Exception 
		System.out.println("InitializingBean-afterPropertiesSet:name is "
				+ name);
	

	public void setBeanName(String name) 
		this.beanName=name;
		System.out.println("BeanNameAware-setBeanName,beanName is " + name);
	

	public void setBeanFactory(BeanFactory beanFactory) throws BeansException 
		this.beanFactory=beanFactory;
		System.out.println("BeanFactoryAware-setBeanFactory,beanFactory is "
				+ beanFactory);
	


MyBeanPostProcessor继承 BeanPostProcessor,做一些后处理:

package com.lxq.test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
 * 
 * @author lxq
 * 一旦MyBeanPostProcessor实现了接口BeanPostProcessor,并在xml中或利用annotation进行bean的注册,那么所有的bean都会执行下面的两个方法
 */
public class MyBeanPostProcessor implements BeanPostProcessor 
	public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException 
		if (bean instanceof Teacher) 
			System.out
					.println("BeanPostProcessor-postProcessAfterInitialization");
		
		return bean;
	

	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException 
		if (bean instanceof Teacher) 
			((Teacher) bean).setName("default_processor");
			System.out
					.println("BeanPostProcessor-postProcessBeforeInitialization,这是在init之前进行修改bean的属性值,把name修改为default_processor");
		
		return bean;
	


BeanLifecycleManangeTest测试类:

package com.lxq.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanLifecycleManangeTest 
	public static void main(String[] args) 
		ApplicationContext ac = new ClassPathXmlApplicationContext(
				new String[]  "beans.xml" );
		/** 调用getbean方法 */
		Teacher t = (Teacher) ac.getBean("teacher");
		t.display();
		/** 调用close方法关闭bean */
		AbstractApplicationContext aac = (AbstractApplicationContext) ac;
		aac.close();
	




输出结果:

这是在调用Teacher的构造方法,将名字由null设置为default_xml_constructor
这是在调用Teacher-setName,将名字由null设置为default_xml_property
BeanNameAware-setBeanName,beanName is teacher
BeanFactoryAware-setBeanFactory,beanFactory is org.springframework.beans.factory.support.DefaultListableBeanFactory@39cf4a2c: defining beans [generatedOrderidServiceBean,其他的省略]; root of factory hierarchy
这是在调用Teacher-setName,将名字由default_xml_property设置为default_processor
BeanPostProcessor-postProcessBeforeInitialization,这是在init之前进行修改bean的属性值,把name修改为default_processor
InitializingBean-afterPropertiesSet:name is default_processor
这是Teacher-init,将名字由default_init设置为default_init
BeanPostProcessor-postProcessAfterInitialization
default_init-null
这是Teacher-destroy

源代码分析:

查看AbstractAutowireCapableBeanFactory的initializeBean,可以看到一个大概的执行过程,查看每个方法中更具体的可以发现基本就是上面所讲的bean的生命周期或者说只是创建过程。

invokeAwareMethods

applyBeanPostProcessorsBeforeInitialization

invokeInitMethods

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;
	





以上是关于spring中Bean的生命周期的主要内容,如果未能解决你的问题,请参考以下文章

spring bean的生命周期是怎样的,代码示例

spring中bean的生命周期是怎么样的

深究Spring中Bean的生命周期

springbean的生命周期是啥?

spring生成bean对象的生命周期都有哪些种类?

转spring bean的生命周期