我的飞书:https://rvg7rs2jk1g.feishu.cn/docx/Frbedr5APoliaixw3KCc2eM2njg
Bean
通过 @Bean 注解,我们可以将创建的对象交给sping容器来进行管理
首先,让我们先实现一个对象例子
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ClassRoom {
private Integer roomNumber;
private String msg;
}
@Configuration
public class ClassRoomConfig {
@Bean
public ClassRoom classRoom(){
return new ClassRoom(1,"这是1号教室");
}
}
@SpringBootTest
public class ConfigTest {
@Autowired
private ApplicationContext context;
@Test
void classRoomTest(){
ClassRoom classRoom = context.getBean("classRoom", ClassRoom.class);
System.out.println(classRoom);
}
}
默认作用域
Bean是有一个默认的作用域的,而这个作用域采用的是单例模式
我们通过输出对象的地址,来判断,此时是否是同一个实例
@Test
void classRoomTest(){
ClassRoom classRoom = context.getBean("classRoom", ClassRoom.class);
classRoom.setMsg("这是美术教室");
System.out.println(classRoom);
ClassRoom classRoom2 = context.getBean("classRoom", ClassRoom.class);
classRoom2.setMsg("这是音乐教室");
System.out.println(classRoom2);
}
结果显示,这俩使用的是同一个实例!!!
当然除了默认的单例模式的作用域,也是有其他的作用域的
同时,在某种特殊的情况下,单例模式也是可以声明多个同名称实例的,但是spring会进行覆盖
作用域介绍
根据官方的说法,总共是有六种作用域,其中后面四种是只能使用在web中
同时,因为spring默认是单例模式,在使用其他几种情况时,需要使用特定的注解
作用域 | 定义 |
singleTon | 单例,这是默认作用域,每一个SpringIoC容器中,相同名称的实例只能有一个 |
prototype | 每次使用bean就会进行创建,这是多例模式,注解:@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) |
request | 请求时,会创建新的bean,注解:@RequestScope |
session | 在一个session周期中,都是同一个bean,注解:@SessionScope |
application | 在一个servletContext周期内,都是同一个bean,注解:@ApplicationScope |
webSocket | 同一个WebSocket,是同一个bean(这个现版本不支持实现) |
在使用这些实例之前,都需要注入实例
@Autowired
private ApplicationContext context;
//方法注入
同时,使用属性注入时,是在程序启动之前就已经注入完成
1.singleTon
@Bean
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
public ClassRoom single(){
return new ClassRoom();
}
@Autowired
private ApplicationContext context;
@Autowired
private ClassRoom single;
@RequestMapping("/single")
public String single(){
ClassRoom single1 = context.getBean("single", ClassRoom.class);
return "context: "+single1 +" 属性注入: "+single;
}
从结果来看,单例模式下,实例只有一个,此时不管怎么进行刷新,都只会有一个实例,不管是不同的请求,还是不同的session,此时都是一样的
2.prototype
@Bean
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public ClassRoom prototype(){
return new ClassRoom();
}
@Autowired
private ApplicationContext context;
@Autowired
private ClassRoom prototype;
@RequestMapping("/prototype")
public String prototype(){
ClassRoom single1 = context.getBean("prototype", ClassRoom.class);
return "context: "+single1 +" 属性注入: "+prototype;
}
从结果来看,使用多例模式创建的实例,是使用一次就会变化一次,但是通过属性注入的实例(默认),是没有进行变化的(在此模式下,属性注入只会注入一次,本质上是单例模式的实例)
第一次生成:
第二次生成:
3.request
@Bean
@RequestScope
public ClassRoom request(){
return new ClassRoom();
}
@Autowired
private ApplicationContext context;
@Autowired
private ClassRoom request;
@RequestMapping("/request")
public String request(){
ClassRoom single1 = context.getBean("request", ClassRoom.class);
return "context: "+single1 +" 属性注入: "+request;
}
结果表明,只要有一次请求时,就会有新的bean生成,同时是属性注入和方法注入都会进行新生成
第一次生成:
第二次生成
4.session
@Bean
@SessionScope
public ClassRoom session(){
return new ClassRoom();
}
@Autowired
private ApplicationContext context;
@Autowired
private ClassRoom session;
@RequestMapping("/session")
public String session(){
ClassRoom single1 = context.getBean("single", ClassRoom.class);
return "context: "+single1 +" 属性注入: "+session;
}
结果表示,不同的session会生成不同的实例,同时是属性注入和方法注入都会进行新生成
5.application
@Bean
@ApplicationScope
public ClassRoom application(){
return new ClassRoom();
}
@Autowired
private ApplicationContext context;
@Autowired
private ClassRoom application;
@RequestMapping("/application")
public String application(){
ClassRoom single1 = context.getBean("application", ClassRoom.class);
return "context: "+single1 +" 属性注入: "+application;
}
结果表示,是没有变化的,貌似可以看作单例模式??但其实他们是有区别的
第一次结果:
第二次结果:
标签:ClassRoom,return,Autowired,作用域,private,Bean,context,public From: https://blog.csdn.net/2303_77303297/article/details/144163417区别!!!
单例是一个 ApplicationContext 同一个
application是一个 ServletContext 同一个
(一个Web中可以有多个 ApplicationContext,但是只会有一个 ServletContext)