bean的作用域和生命周期
一、bean的作用域
在 Spring
中,那些组成应用程序的主体及由 Spring IOC
容器所管理的对象,被称之为 bean
。
简单地讲,bean
就是由 IOC
容器初始化、装配及管理的对象。
而作用域代表的 bean
的创建存在方式,可以在哪里使用
我们分别可以使用以下这四种情况
scope取值 |
含义 |
创建对象的时机 |
singleton(默认) |
在一个IOC容器中,这个 bean 对象只有一个实例 |
IOC容器初始时创建单例 bean |
prototype |
在一个IOC容器中,这个 bean 有多个实例 |
获取 bean 的时候 |
request |
每一次 http 请求,都会创建一个 bean |
每一次 http 请求的时候 |
session |
同一个 http session 中,有且仅有一个 bean |
产生新的 http session 会话的时候 |
后面两种不做要求,仅用在基于 web
的 Spring ApplicationContext
环境
演示 singleton
和 prototype
的区别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package com.banmoon.test.scope; import com.banmoon.test.User; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; @Configuration public class BeanScope { @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON) @Bean(name = "user") public User user() { return new User(1, "banmoon"); } public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanScope.class); User user = context.getBean(User.class); System.out.println(user); System.out.println("========== 分割线 =========="); User user1 = context.getBean(User.class); System.out.println(user1); } }
|
单例启动,结果如下,两次对象地址打印是一致的
将 @Scope
注解的值改为 prototype
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package com.banmoon.test.scope; import com.banmoon.test.User; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; @Configuration public class BeanScope { @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Bean(name = "user") public User user() { return new User(1, "banmoon"); } public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanScope.class); User user = context.getBean(User.class); System.out.println(user); System.out.println("========== 分割线 =========="); User user1 = context.getBean(User.class); System.out.println(user1); } }
|
可以看到他们的地址是不一致的
还有一点,注意上面 spring
打印的 debug
日志,可以清楚的看到 bean
创建的时间节点,
单例 bean
是在 IOC
容器初始化后,马上就进行了创建
原型 bean
是在每次创建时才进行创建,这也是每次获取不一致的原因所在
二、bean的生命周期
什么是 bean
的生命周期,就是一个 bean
从出生到死亡的过程,其中经历了哪些步骤,了解这些步骤,我们就可以更加清晰了解 bean
的运行规律。
总的来说,bean
的生命周期可以规划为下面这个步骤
-
初始化,也就是调用构造方法
-
通过 set
方法进行赋值
-
处理 Aware
系列接口,具体可以查看它的几个子接口具体是做什么的
-
InitializingBean
接口,调用其初始化方法
-
调用在 bean
标签中指定的初始化方法
-
初始化完成,进行使用
-
DisposableBean
接口,调用其销毁方法
-
调用在 bean
标签中指定的销毁方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| package com.banmoon.test.lifecycle; import lombok.Getter; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean;
@Getter public class User implements InitializingBean, DisposableBean, BeanNameAware { private String name; public User() { System.out.println("1、调用无参构造进行创建"); } public void setName(String name) { System.out.println("2、通过set方法进行设置属性"); this.name = name; } @Override public void setBeanName(String s) { System.out.println("3、Aware系列接口,处理相关的逻辑"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("4、InitializingBean接口,初始化方法"); } public void myInit() { System.out.println("5、在bean标签中指定的初始化方法"); } @Override public void destroy() throws Exception { System.out.println("7、DisposableBean接口,销毁方法"); } public void myDestroy() { System.out.println("8、在bean标签中指定的销毁方法"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package com.banmoon.test.lifecycle; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; public class Main { @Bean(name = "user", initMethod = "myInit", destroyMethod = "myDestroy") public User user() { User user = new User(); user.setName("user"); return user; } public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class); User bean = context.getBean("user", User.class); System.out.println("6、进行模拟使用:" + bean.getName()); context.close(); } }
|
代码比较简单,直接查看运行结果