Bean的生命周期
生命周期就是对象从创建开始到最终销毁的整个过程 , Spring其实就是一个管理Bean对象的工厂,它负责对象的创建和销毁等
-
Bean生命周期的管理可以参考Spring的源码:
AbstractAutowireCapableBeanFactory
类的doCreateBean()方法
-
研究生命周期的意义:在哪个时间节点上调用了哪个类的哪个方法,把需要在某个特殊的时间点上执行的一段代码放到对应节点上,然后到点会自动被调用
Bean的生命周期之五步
第一步:实例化Bean(调用无参数构造方法)
第二步:给Bean属性赋值(调用set方法)
第三步:初始化Bean(会调用Bean的init方法, 这个init方法需要自己写,并且在配置文件中需要使用init-method
属性指定)
第四步:使用Bean
第五步:销毁Bean(会调用Bean的destroy方法, 这个destroy方法需要自己写,并且在配置文件中需要使用destroy-method
属性指定)
- 只有手动关闭Spring容器, bean的销毁方法才会被调用,需要向下转型执行
ClassPathXmlApplicationContext特有的close方法
定义一个Bean
public class User {private String name;public User() {System.out.println("1.实例化Bean");}public void setName(String name) {this.name = name;System.out.println("2.Bean属性赋值");}//配置bean的初始化方法public void initBean(){System.out.println("3.初始化Bean");}//配置bean的销毁方法public void destroyBean(){System.out.println("5.销毁Bean");}
}
编写spring的配置文件: init-method
属性指定初始化方法名, destroy-method
属性指定销毁方法名
<?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 id="userBean" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean"><property name="name" value="zhangsan"/></bean>
</beans>
测试结果的执行顺序: 1.实例化Bean-->2.Bean属性赋值-->3.初始化Bean-->4.使用Bean-->5.销毁Bean
public class BeanLifecycleTest {@Testpublic void testLifecycle(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");//以下这行代码执行了1.实例化Bean-->2.Bean属性赋值-->3.初始化BeanUser userBean = applicationContext.getBean("userBean", User.class);System.out.println("4.使用Bean");// 必须手动关闭Spring容器才会销毁Bean从而执行Bean的销毁方法ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;context.close();}
}
Bean生命周期之七步(掌握)
如果你还想在besn的初始化前和初始化后添加代码,需要加入Bean后处理器
(编写一个类实现BeanPostProcessor接口并且实现before和after方法)
- Bean后处理器将作用于整个配置文件中所有的bean
编写日志的Bean后处理器
实现BeanPostProcessor接口并实现postProcessBeforeInitialization和postProcessAfterInitialization
方法
- 这两个方法都有两个参数:第一个参数是刚创建的bean对象, 第二个参数是bean的名字
public class LogBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("Bean后处理器的before方法执行,即将开始初始化");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("Bean后处理器的after方法执行,已完成初始化");return bean;}
}
在spring的配置文件中配置Bean后处理器
(作用于当前配置文件中所有的Bean),并手动指定Bean的初始化方法和销毁方法
<?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--><bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/><!--普通bean--><bean id="userBean" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean"><property name="name" value="zhangsan"/></bean>
</beans>
测试结果: 1.实例化Bean–>2.Bean属性赋值–>Bean后处理器的before方法–>3.初始化Bean–>Bean后处理器的after方法–>4.使用Bean–>5.销毁Bean
public class BeanLifecycleTest {@Testpublic void testLifecycle(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");// 以下这行代码执行了1.实例化Bean-->2.Bean属性赋值-->Bean后处理器的before方法-->3.初始化Bean-->Bean后处理器的after方法User userBean = applicationContext.getBean("userBean", User.class);System.out.println("4.使用Bean");// 必须手动关闭Spring容器才会销毁Bean从而执行Bean的销毁方法ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;context.close();}
}
Bean生命周期之十步(了解)
多添加了三个点位用来检查你这个Bean是否实现了某些特定的接口,如果实现了这些接口则Spring容器会调用这些接口中的方法
- 调用这些接口中的方法目的是为了给你传递一些数据,让你更加方便使用
点位1:在Bean后处理器
的before方法之前(检查Bean是否实现了Aware相关的接口BeanNameAware、BeanClassLoaderAware、BeanFactoryAware)
- 当Bean实现了BeanNameAware,Spring会将Bean的名字传递给Bean
- 当Bean实现了BeanClassLoaderAware,Spring会将加载该Bean的类加载器传递给Bean
- 当Bean实现了BeanFactoryAware,Spring会将Bean工厂对象传递给Bean
点位2:在Bean后处理器
的before方法之后(检查Bean是否实现了InitializingBean接口)
点位3:使用Bean之后或者说销毁Bean之前(检查Bean是否实现了DisposableBean接口)
User类实现了BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean
5个接口并实现它们的所有方法
- InitializingBean接口的afterPropertiesSet方法早于init-method的执行 , DisposableBean接口的destroy方法早于destroy-method的执行
public class User implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {private String name;public User() {System.out.println("1.实例化Bean");}public void setName(String name) {this.name = name;System.out.println("2.Bean属性赋值");}public void initBean(){System.out.println("6.初始化Bean");}public void destroyBean(){System.out.println("10.销毁Bean");}@Overridepublic void setBeanClassLoader(ClassLoader classLoader) {System.out.println("3.类加载器:" + classLoader);}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("3.Bean工厂:" + beanFactory);}@Overridepublic void setBeanName(String name) {System.out.println("3.bean名字:" + name);}@Overridepublic void destroy() throws Exception {System.out.println("9.DisposableBean destroy");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("5.afterPropertiesSet执行");}
}
编写Bean后处理器
重写postProcessBeforeInitialization和postProcessAfterInitialization方法
public class LogBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("4.Bean后处理器的before方法执行,即将开始初始化");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("7.Bean后处理器的after方法执行,已完成初始化");return bean;}
}
在spring的配置文件中配置Bean后处理器
(作用于当前配置文件中所有的Bean),并手动指定Bean的初始化方法和销毁方法
<?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--><bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/><!--手动指定Bean的初始化方法和销毁方法--><bean id="userBean" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean"><property name="name" value="zhangsan"/></bean>
</beans>
测试结果
public class BeanLifecycleTest {@Testpublic void testLifecycle(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");User userBean = applicationContext.getBean("userBean", User.class);System.out.println("8.使用Bean");// 必须手动关闭Spring容器才会销毁Bean从而执行Bean的销毁方法ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;context.close();}
}
Bean的不同管理方式
Spring容器根据Bean的作用域来选择管理方式
对于singleton作用域的Bean
: Spring能够精确地知道该Bean何时被创建,何时初始化完成以及何时被销毁(完整的生命周期)对于prototype作用域的Bean
: Spring只负责Bean的创建, 当客户端程序获取到该Bean后,Spring容器将不再跟踪其生命周期 , 剩下的操作交给客户端管理
将spring配置文件中User类的scope属性设置为prototype
<?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 id="userBean" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean" scope="prototype"><property name="name" value="zhangsan"/></bean><!--配置Bean后处理器,这个后处理器将作用于当前配置文件中所有的bean--><bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/>
</beans>
public class BeanLifecycleTest {@Testpublic void testLifecycle(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");User userBean = applicationContext.getBean("userBean", User.class);System.out.println("8.使用Bean");// 当客户端程序获取到该Bean后,容器将不再跟踪其生命周期即生命周期方法不再执行,剩下的操作交给客户端管理ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;context.close();}
}
Spring管理自己new的对象
有些时候可能会需要将我们自己new的java对象交给Spring容器管理,此时需要创建默认的DefaultListableBeanFactory工厂
对象用来注册Bean并指定Bean的id
// 定义Bean
public class User {
}
public class RegisterBeanTest {@Testpublic void testBeanRegister(){// 自己new的User对象User user = new User();// com.powernode.spring6.bean.User@79e2c065System.out.println(user);// 创建默认列表BeanFactory对象注册BeanDefaultListableBeanFactory factory = new DefaultListableBeanFactory();// 注册Beanfactory.registerSingleton("userBean", user);// 根据id从spring容器中获取beanUser userBean = factory.getBean("userBean", User.class);// com.powernode.spring6.bean.User@79e2c065System.out.println(userBean);}
}