目录
何为Spring生命周期
Bean的生命周期
生命周期图
生命周期的流程
Spring Bean的单列与多列的作用域
单例Bean的配置方式
注解方式
XML方式
单列案列
后端Servlet
测试类
Spring Config文件配置
何为Spring生命周期
Bean的生命周期
对于一个Bean的生命周期,其实非常简单,无非就是从创建对象到销毁的过程,但是Spring作为一个可扩展的框架,其在Bean的创建和销毁过程中加入了非常多的扩展点,这也是为什么Spring能够蓬勃发展至今的一个原因。Bean的生命周期大体可以总结为以下几个阶段:
Bean的定义
Bean的注册
Bean的创建
Bean的注入
Bean的初始化
Bean的销毁
生命周期图
生命周期的流程
1. Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化
2. Bean实例化后将Bean的引入和值注入到Bean的属性中
3. 如果Bean实现了BeanNameAware接口的话,Spring将Bean的id传递给setBeanName()方法
BeanNameAware的作用:让Bean获取自己在BeanFactory配置中的名字。
4. 如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
BeanFactoryAware的作用:让Bean获取配置他们的BeanFactory的引用。
5. 如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入
为什么使用ApplicationContextAware接口:在spring项目中,类之间的关系是spring容器来管理的,但是一个项目中有些类不受spring容器管理缺需要使用受spring管理的bean,这时候不能通过正常的方式注入bean,这时候spring给我们提供了ApplicationContextAware接口,我们可以编写一个工具类来实现ApplicationContextAware,通过工具类来获取我们需要的bean然后供不在spring容器中的类调用。
6. 如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法
postProcessBeforeInitialization()方法:初始化方法之前调用
7. 如果Bean实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用
afterPropertiesSet()方法:初始化方法。如果使用了init-method声明了初始化方法,则执行顺序为:先执行afterPropertiesSet()方法,再执行init-method声明的方法。
8. 如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法
postProcessAfterInitialization()方法:初始化方法之后调用
9. 此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁
10. 如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用
destory()方法:销毁前调用。如果使用了destory-method声明了销毁方法,则执行顺序为:先执行destory()方法,再执行destory-method声明的方法。
Spring Bean的单列与多列的作用域
单例模式(Singleton):
单例是指在整个应用程序上下文中只创建一个实例,并且所有的请求都会返回同一个实例
默认情况下,Spring容器中的Bean都是单例的
单例模式适用于那些不需要维护状态的Bean,或者对资源消耗较大的Bean进行共享
缺点:使用单例会有变量污染,单例是根据spring上下文初始化;容器生对象生,容器死对象死多例模式(Prototype):
多例是指每次请求时都会创建一个新的实例,每个实例都是独立的
每次从容器中获取该Bean时,都会创建一个新的实例
多例模式适用于那些需要维护状态的Bean,或者对资源消耗较小的Bean进行独立创建
缺点:使用多例及其消耗内存,多例使用时候才会创建,销毁跟着jvm走。
单例Bean的配置方式
注解方式
// 使用注解配置单例Bean
@Component
@Scope("singleton")
public class MySingletonBean {
// ...
}
// 使用注解配置多例Bean
@Component
@Scope("prototype")
public class MyPrototypeBean {
// ...
}
XML方式
<!-- 使用XML配置单例Bean -->
<bean id="paramAction" class="com.zking.beanlife.ParamAction" scope="singleton">
<!-- ... -->
</bean>
<!-- 使用XML配置多例Bean -->
<bean id="paramAction" class="com.zking.beanlife.ParamAction" scope="prototype">
<!-- ... -->
</bean>
单列案列
先建一个类,创建它的三种方法
package com.zking.beanlife;
public class InstanceFactory {
public void init() {
System.out.println("初始化方法");
}
public void destroy() {
System.out.println("销毁方法");
}
public void service() {
System.out.println("业务方法");
}
}
后端Servlet
package com.zking.beanlife;
import java.util.List;
public class ParamAction {
private int age;
private String name;
private List<String> hobby;
private int num = 1;
// private UserBiz userBiz = new UserBizImpl1();
public ParamAction() {
super();
}
public ParamAction(int age, String name, List<String> hobby) {
super();
this.age = age;
this.name = name;
this.hobby = hobby;
}
public void execute() {
// userBiz.upload();
// userBiz = new UserBizImpl2();
System.out.println("this.num=" + this.num++);
System.out.println(this.name);
System.out.println(this.age);
System.out.println(this.hobby);
}
}
测试类
package com.zking.beanlife;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
/*
* spring bean的生命週期
* spring bean的單例多例
*/
public class Demo2 {
// 体现单例与多例的区别
@Test
public void test1() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
// InstanceFactory instanceFactory = (InstanceFactory) applicationContext.getBean("instanceFactory");
// ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
ParamAction p1 = (ParamAction) applicationContext.getBean("paramAction");
ParamAction p2 = (ParamAction) applicationContext.getBean("paramAction");
// System.out.println(p1==p2);
p1.execute();
p2.execute();
// 单例时,容器销毁instanceFactory对象也销毁;多例时,容器销毁对象不一定销毁;
applicationContext.close();
}
// 体现单例与多例的初始化的时间点 instanceFactory
@Test
public void test2() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
}
// BeanFactory会初始化bean对象,但会根据不同的实现子类采取不同的初始化方式
// 默认情况下bean的初始化,单例模式立马会执行,但是此时XmlBeanFactory作为子类,单例模式下容器创建,bean依赖没有初始化,只有要获取使用bean对象才进行初始化
@Test
public void test3() {
// ClassPathXmlApplicationContext applicationContext = new
// ClassPathXmlApplicationContext("/spring-context.xml");
Resource resource = new ClassPathResource("/spring-context.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
// InstanceFactory i1 = (InstanceFactory) beanFactory.getBean("instanceFactory");
}
}
Spring Config文件配置