spring之一 bean初始化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/nongfuyumin/article/details/79559685

spring之一 bean初始化

spring bean生命周期
  • Bean容器找到配置文件中Spring Bean的定义。
  • Bean容器利用Java Reflection API创建一个Bean的实例。
  • 如果涉及到一些属性值 利用set方法设置一些属性值。
  • 如果Bean实现了BeanNameAware接口,调用setBeanName()方法,传入Bean的名字。
  • 如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
  • 如果Bean实现了BeanFactoryAware接口,调用setBeanClassLoader()方法,传入BeanFactory
  • 与上面的类似,如果实现了其他*Aware接口,就调用相应的方法。
  • 如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessBeforeInitialization()方法
  • 如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。
  • 如果Bean在配置文件中的定义包含init-method属性,执行指定的方法。
  • 如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessAfterInitialization()方法
  • 当要销毁Bean的时候,如果Bean实现了DisposableBean接口,执行destroy()方法。
  • 当要销毁Bean的时候,如果Bean在配置文件中的定义包含destroy-method属性,执行指定的方法。
根据代码debug来看spring是怎么初始化一个bean的,先简单写一个service,代码如下

package com.spring.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class CountryService implements InitializingBean{
	Logger logger = LoggerFactory.getLogger(CountryService.class);
	public String getCountry(){
		return "china";
	}
	 public CountryService() {
		logger.info("construct");
	}
	@Override
	public void afterPropertiesSet() throws Exception {
		// TODO Auto-generated method stub
		logger.info("afterPropertiesSet");
	}

}
bean配置文件bean-definition.xml如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:lang="http://www.springframework.org/schema/lang"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/lang
        http://www.springframework.org/schema/lang/spring-lang.xsd">
	<bean id="countryServiceBean" abstract="false"
		class="com.spring.service.CountryService">
	</bean>
</beans>
CommonBeanPostProcessor代码如下
package com.spring.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class CommonBeanPostProcessor implements BeanPostProcessor{
	Logger logger = LoggerFactory.getLogger(CommonBeanPostProcessor.class);
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		logger.info("postProcessBeforeInitialization");
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		logger.info("postProcessAfterInitialization");
		return bean;
	}

}


测试文件如下
package com.spring;

import java.util.Iterator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import com.spring.service.CommonBeanPostProcessor;

public class XmlDefinitionTest {
	static Logger logger = LoggerFactory.getLogger(XmlDefinitionTest.class);
	public static void main(String args[]){
		Resource xmlResource = new ClassPathResource("bean-definition.xml");
		XmlBeanFactory beanFactory = new XmlBeanFactory(xmlResource);
		Iterator<String> beanNameIt= beanFactory.getBeanNamesIterator();
		beanFactory.addBeanPostProcessor(new CommonBeanPostProcessor());
		while(beanNameIt.hasNext()){
			String beanName = beanNameIt.next();
			Object object = beanFactory.getBean(beanName);
			logger.info(object.toString());
		}
	}
}
在main方法里面打个断点,可以看到从xml文件中注册bean的整个过程。如图所示,这个过程中spring并没有实例化bean,只是把bean注册到spring容器中。


然后在getBean那一行再打个断点,调用栈如下图




在initializeBean方法中首先调用invokeAwareMethods方法,这个方法的内容对应bean声明周期中的
  • 如果Bean实现了BeanNameAware接口,调用setBeanName()方法,传入Bean的名字。
  • 如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
  • 如果Bean实现了BeanFactoryAware接口,调用setBeanClassLoader()方法,传入BeanFactory

接下来调用applyBeanPostProcessorsBeforeInitialization方法,对应于bean声明周期中的
如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessBeforeInitialization()方法
然后调用invokeInitMethods方法,具体如下
对应bean声明周期中的
  • 如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。
  • 如果Bean在配置文件中的定义包含init-method属性,执行指定的方法。

然后再调用postProcessAfterInitialization方法,对应bean生命周期中的
如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessAfterInitialization()方法
到此一个bean就实例化完成,然后就可以使用了。
查看程序执行结果

猜你喜欢

转载自blog.csdn.net/nongfuyumin/article/details/79559685