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;
	}





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值