1.Bean的生命周期49是什么?
Spring实际上是一家管理Bean对象的工厂。它负责创建对象、销毁对象等。
所谓生命周期,就是对象从创造到最终销毁的整个过程。
Bean对象什么时候创建?
创建Bean对象前后会调用哪些方法?
Bean对象什么时候被销毁?
Bean对象销毁前后调用哪些方法?
2.为什么要知道Bean的生命周期49?事实上,生命周期的本质是:在哪个时间节点调用哪种方法。
在这条生命线上,我们需要充分了解哪些特殊的时间节点。
只有当我们知道特殊的时间节点在哪里,我们才能确定代码写在哪里。
我们可能需要在特定的时间点执行一个特定的代码,这个代码可以放在这个节点上。当生命线到达这里时,它自然会被调用。
3.Bean生命周期5步49管理Bean生命周期,可参考Spring的源代码:AbstractautowirecapablebeanFactorydocrebean()方法。
Bean的生命周期大致可以分为五个步骤:
●第一步:实例化Beann
●第二步:Bean属性赋值
●第三步:Bean初始化
●第四步:使用Beann
●第五步:销毁Beann
3.1编写测试程序:49定义一个Bean
package com.powernode.spring6.bean;import org.springframework.beans.BeansException;import org.springframework.beans.factory.*;/** * * 如果Bean的生命周期遵循粗略的五个步骤: 49 * 第一步:实例Bean(调用无参数结构方法。) * 第二步:赋予Bean属性(调用set方法)。) * 第二步:给Bean属性赋值(调用set方法)。 * 第三步:初始化Bean(会调用Bean的init方法。注:这种init方法需要自己写,自己匹配。) * 第四步:使用Beann * 第五步:销毁Bean(会调用Bean的destroy方法。注:这种destroy方法需要自己写,自己配。) **/public class User{ private String name; public void setName(String name) { System.out.println(第二步:赋值对象的属性。"); this.name = name; } public User() { System.out.println(一步:实施无参数结构方法。"); } // 这种方法需要自己写,自己匹配。方法名随意。 public void initBean(){ System.out.println(第三步:初始化Bean。"); } // 这种方法需要自己写,自己匹配。方法名随意。 public void destroyBean(){ System.out.println(第五步:销毁Bean。"); }// @Override// public void setBeanClassLoader(ClassLoader classLoader) {// System.out.println(Bean这类加载器:" + classLoader);// }//// @Override// public void setBeanFactory(BeanFactory beanFactory) throws BeansException {// System.out.println("生产这个Bean的工厂对象是:" + beanFactory);// }//// @Override// public void setBeanName(String name) {// System.out.println(”这个Bean的名字是:" + name);// }//// @Override// public void afterPropertiesSet() throws Exception {// System.out.println("InitializingBean's afterPropertiesset执行。");// }//// @Override// public void destroy() throws Exception {// System.out.println("DisposableBean's 执行destroy方法”);// }}
<!-- 研究bean的生命周期 49--> <!--初始化方法和销毁方法需要手动指定。--> <bean id="user" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean"> <property name="name" value="zhangsan"/> </bean>
////测试bean的生命周期 49 @Test public void testBeanLifecycleTest(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); User user = applicationContext.getBean("user", User.class); System.out.println(第四步:使用beann:"+user); // 注:Spring容器必须手动关闭,这样,Spring容器就会销毁Beann. ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext; context.close(); }
3.2应注意:49
●第一:只有正常关闭spring容器,bean的销毁方法才会被调用。
●第二:ClasspathXmlaplicationcontext类有close()方法。
●第三:init-method在配置文件中指定初始化方法。destroy-method指定销毁方法。
3.2.1再次强调Bean生命周期五步:
第一步:实例化Beann
第二步:Bean属性赋值
第三步:Bean初始化
第四步:使用Beann
第五步:销毁Beann
4.Bean生命周期7步504.1Bean生命周期7步:比五步加的两步在哪里?在Bean初始化的前后。
第一步:实例化Beann
第二步:Bean属性赋值
第三步:执行“Bean后处理器”的before方法。
第四步:Bean初始化
第五步:执行“Bean后处理器”的after方法。
第六步:使用Beann:
第七步:销毁Beann
在以上五个步骤中,第三步是初始化Bean。如果您想在初始化前后添加代码,可以添加“Bean后处理器”。
编写BeanPostProcessor类,并重写before和after方法:
package com.powernode.spring6.bean;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;/** * 日志Bean后处理器。 50 **/public class LogBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println(执行bean后处理器的before方法。"); return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName); } // 该方法有两个参数: // 第一个参数:刚创建的bean对象。 // 第二个参数:bean的名字。 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println(”执行Bean后处理器的after方法。"); return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); }}
spring.Bean后处理器配置在xml文件中:
<!--配备Bean后处理器。 50--> <!--注:Bean后处理器将作用于整个配置文件中的所有Bean。--> <bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/>
4.2注意50
一定要注意:在spring.Bean后处理器配置在xml文件中,将作用于当前配置文件中的所有Bean。
如果加上Bean后处理器,Bean的生命周期是7步:
5.Bean生命周期10步515.1Bean生命周期10步:比七步加的三步在哪里?515.1.1点位1:在“Bean后处理器”before方法之前
做了什么事?
检查Bean是否实现了与Aware相关的接口,如果实现了接口,则调用这些接口中的方法。
然后调用这些方法的目的是向您传递一些数据,使您更容易使用。
5.1.2点位2:before方法后的“bean后处理器”
做了什么事?
检查Bean是否实现了InitializingBean接口,如果实现了,则调用接口中的方法。
5.1.3点位3:使用Bean后,或在销毁Bean之前
做了什么事?
检查Bean是否实现了DisposableBean接口,如果实现了,则调用接口中的方法。
5.1.加入这三个点的特点:检查Bean是否实现了某些特定的接口,如果实现了这些接口,Spring容器将调用此接口中的方法。
若按源代码跟踪,可分为10步:
5.2上图检查Bean是否实现了Aware的相关接口是什么意思?51与Aware相关的接口包括:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
●当Bean实现BeanNameAware时,Spring会将Bean的名字传递给Bean。
●当Bean实现BeanClassloaderaware时,Spring将加载Bean的类加载器传递给Bean。
●当Bean实现BeanFactoryAware时,Spring将Bean工厂的对象传递给Bean。
5.3测试上述10个步骤,使User类实现5个接口,并实现所有方法:51●BeanNameAware
●BeanClassLoaderAware
●BeanFactoryAware
●InitializingBean
●DisposableBean
package com.powernode.spring6.bean;import org.springframework.beans.BeansException;import org.springframework.beans.factory.*;/** * * 如果Bean的生命周期遵循粗略的五个步骤: 49 * 第一步:实例Bean(调用无参数结构方法。) * 第二步:赋予Bean属性(调用set方法)。) * 第三步:初始化Bean(会调用Bean的init方法。注:这种init方法需要自己写,自己匹配。) * 第四步:使用Beann * 第五步:销毁Bean(会调用Bean的destroy方法。注:这种destroy方法需要自己写,自己配。) **/public class User implements BeanNameAware, BeanClassLoaderAware,BeanFactoryAware,InitializingBean,DisposableBean{ private String name; public void setName(String name) { System.out.println(第二步:赋值对象的属性。"); this.name = name; } public User() { System.out.println(一步:实施无参数结构方法。"); this.name = name; } public User() { System.out.println(第一步:实施无参数结构方法。); } // 这种方法需要自己写,自己匹配。方法名随意。 public void initBean(){ System.out.println(第四步:初始化Bean。"); } // 这种方法需要自己写,自己匹配。方法名随意。 public void destroyBean(){ System.out.println(第七步:销毁Bean。"); } @Override public void setBeanClassLoader(ClassLoader classLoader) { System.out.println(Bean这类加载器:" + classLoader); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("生产这个Bean的工厂对象是:" + beanFactory); } @Override public void setBeanName(String name) { System.out.println(”这个Bean的名字是:" + name); } @Override public void afterPropertiesSet() throws Exception { System.out.println("InitializingBean's afterPropertiesset执行。"); } @Override public void destroy() throws Exception { System.out.println("DisposableBean's 执行destroy方法”); }}
package com.powernode.spring6.bean;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;/** * 日志Bean后处理器。 50 **/public class LogBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println(第三步:执行Bean后处理器的before方法。"); return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName); } // 该方法有两个参数: // 第一个参数:刚创建的bean对象。 // 第二个参数:bean的名字。 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println(第五步:执行Bean后处理器的after方法。"); return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); }}
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--配备Bean后处理器。--配备Bean后处理器。 50--> <!--注:Bean后处理器将作用于整个配置文件中的所有Bean。--> <bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/><!-- 研究bean的生命周期 49--> <!--初始化方法和销毁方法需要手动指定。--> <bean id="user" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean"> <property name="name" value="zhangsan"/> </bean><!-- <bean id="vip" class="com.powernode.spring6.bean.Vip"/>--></beans>
package com.powernode.spring6.test;import com.powernode.spring6.bean.User;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class BeanLifecycleTest { ////测试bean的生命周期 49-50 @Test public void testBeanLifecycleTest(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); User user = applicationContext.getBean("user", User.class); System.out.println(第六步:使用bean:"+user); // 注:Spring容器必须手动关闭,这样,Spring容器就会销毁Beann. ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext; context.close(); }}
通过测试可以看出:
●InitializingBean的方法早于init-method的执行。
●Disposablebean的方法早于destroy-method的执行。
对于SpringBean的生命周期,掌握之前的7步。够了。
6.Bean有不同的功能域和不同的管理模式Spring根据Bean的作用域选择管理模式。
●对于singleton作用域的Bean,Spring可以准确地知道Bean何时创建,何时初始化,何时销毁;
●对于prototype作用域的Bean,Spring只负责创建。当容器创建Bean的例子时,Bean的例子将交给客户端代码管理,Spring容器将不再跟踪其生命周期。
让我们把以前的Userspring放在之前.xml文件中的配置scope设置为prototype:
<!--配备Bean后处理器。 50--> <!--注:Bean后处理器将作用于整个配置文件中的所有Bean。--> <bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/><!-- 研究bean的生命周期 49--> <!--初始化方法和销毁方法需要手动指定。--> <bean id="user" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean" scope="prototype"> <property name="name" value="zhangsan"/> </bean>
/** * Spring容器只管理singletonBean的完整生命周期。 * 如果是prototype作用域的Bean,Spring容器只负责Bean的初始化。 * 一旦客户端程序获得Bean,Spring容器将不再管理对象的生命周期。 */ ////测试bean的生命周期 49-50 @Test public void testBeanLifecycleTest(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); User user = applicationContext.getBean("user", User.class); System.out.println(第六步:使用bean:"+user); // 注:Spring容器必须手动关闭,这样,Spring容器就会销毁Beann. ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext; context.close(); }
通过测试一目了然。前8步只执行,第9步和第10步没有执行。
7.如何让Spring管理自己new的对象53?有时候我们可能会遇到这样的需求。java对象是我们自己的new,然后我们希望Spring容器管理这个对象。如何实现?
package com.powernode.spring6.bean;/** * 如何让Spring管理自己new的对象? 53 **/public class Student {}
////如何让Spring管理自己new的对象? 53 @Test public void testRegisterBean(){ // 自己new的对象 Student student = new Student(); System.out.println(student); // 将上述new对象纳入Spring容器进行管理。半路交给Spring进行管理。 DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); factory.registerSingleton("studentBean",student); // 从spring容器中获取 Object studentBean = factory.getBean("studentBean"); System.out.println(studentBean); }