在 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的区别
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
User user1 = context.getBean(User.class);
System.out.println(user1);
}
}单例启动,结果如下,两次对象地址打印是一致的

将 @Scope注解的值改为 prototype
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
User user1 = context.getBean(User.class);
System.out.println(user1);
}
}可以看到他们的地址是不一致的

还有一点,注意上面
spring打印的debug日志,可以清楚的看到bean创建的时间节点, 单例bean是在IOC容器初始化后,马上就进行了创建 原型bean是在每次创建时才进行创建,这也是每次获取不一致的原因所在
什么是 bean的生命周期,就是一个 bean从出生到死亡的过程,其中经历了哪些步骤,了解这些步骤,我们就可以更加清晰了解 bean的运行规律。
总的来说,bean的生命周期可以规划为下面这个步骤
set方法进行赋值
Aware系列接口,具体可以查看它的几个子接口具体是做什么的
InitializingBean接口,调用其初始化方法
bean标签中指定的初始化方法
DisposableBean接口,调用其销毁方法
bean标签中指定的销毁方法
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;
/**
* @author banmoon
*/
@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标签中指定的销毁方法");
}
} 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();
}
}代码比较简单,直接查看运行结果
