相信大多数初级程序员在面试的时候都面试过Spring中bean的生命周期,大多数人对其不太了解,认为周期一般都是: 初始化->使用->销毁就行了,Spring对bean的管理增加了很多操作,所以Spring中bean的生命周期上涉及的内容就比较多了,本文写个简单的例子来说明一下。
public class User implements InitializingBean { private String name; private int age; User(){ System.out.println("User Constructor"); } public void init(){ System.out.println("User Init"); } public void destroy(){ System.out.println("Destroy Method"); } public String getName() { return name; } public void setName(String name) { System.out.println("User setName"); this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public void afterPropertiesSet() throws Exception { System.out.println("User afterPropertiesSet"); } }
public class MyBeanPostProcessor implements BeanPostProcessor { MyBeanPostProcessor(){ System.out.println("MyBeanPostProcessor Constructor"); } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("MyBeanPostProcessor -> BeforeInitialization :"+bean); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("MyBeanPostProcessor -> AfterInitialization :"+bean); return bean; } }
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { MyBeanFactoryPostProcessor(){ System.out.println("MyBeanFactoryPostProcessor Constructor"); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { BeanDefinition userDefinition = beanFactory.getBeanDefinition("user"); MutablePropertyValues propertyValues = userDefinition.getPropertyValues(); propertyValues.addPropertyValue("age",10); System.out.println("BeanFactoryPostProcessor -> postProcessBeanFactory"); } }
XML中的配置
<bean id="user" class="com.jack.User" init-method="init" destroy-method="destroy"> <property name="name" value="JACK"></property> </bean> <bean class="com.jack.MyBeanPostProcessor"></bean> <bean class="com.jack.MyBeanFactoryPostProcessor"></bean>
测试代码:
public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:beans.xml"); User user = (User) applicationContext.getBean("user"); System.out.println("user=" + user); //这段代码是必须的,当关闭容器的时候会销毁Bean ((ClassPathXmlApplicationContext) applicationContext).close(); }
看一下执行结果:
上面代码中有两个类BeanPostProcessor与BeanFactoryPostProcessor说一下:
这两个类都是后置处理器,其中BeanPostProcessor是Bean对象的后置处理器,主要用来对实例化的bean对象做处理,而BeanFactoryPostProcessor是Bean工厂的后置处理器,Bean工厂内部管理的主要是BeanDefinition,所以它一般用来做对BeanDefinition的处理,在这里可以修改XML中的配置结果,例如给属性设置值,修改对象的单例。正常思考一下BeanFactoryPostProcessor肯定要执行在BeanPostProcessor之前,因为先有工厂再有实例,并且先有模板再有对象,前者操作的是模板,如果先有了对象了改模板就没有意义了。
执行结果从上往下看:
默认情况下Spring使用的是饿汉式单例设计模式,在容器初始化的时候就做了Bean的初始化操作,如果是懒加载的也就是懒汉式设计模式和非单例的会在getBean()的时候执行Bean的初始化操作。
正常情况下我们认为生命周期也就是Init -> Use -> Destroy,Spring在Bean的生命周期中增加了N多步操作,对我们来讲是没有多大意义的,但是对构建Spring的其他框架来说有着重要的意义,因为其他框架中可能涉及到对Bean的一些处理需要精细到每一步操作,例如看一下BeforeInit和AfterInit是不是比较熟悉,这和我们学的AOP有点相似,没错这里可能创建的类可能在其他框架中需要动态代理,所以加了PostProcess类的操作。
整个Bean初始化操作周期具体执行的源代码在这一步,改天不加班的时候写个生命周期源码解读文章:
// Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory);
而XML中的bean配置转换为BeanDefinition的操作在初始化Bean工厂的时候执行的:
// Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
这两个代码都是在加载配置文件中的refresh()方法中,不管是那种bean注入方式都会调用refresh()方法,这可以说是Spring中比较复杂的代码了,涉及的内容比较多,有耐心的可以自己看一下:
public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super(parent); setConfigLocations(configLocations); if (refresh) { refresh(); } }
这里面有几个误解的地方需要注意一下: