在Spring Ioc和DI阶段我们知道了Spring是如何帮助我们管理对象的,通过@Controller,@Service,@Component@Configuration和@Bean来声明对象的,通过ApplicationContext来取出对象的。接下来我们做一个小实验,如果我们在ApplicationContext中多次获取同一个对象那会有什么结果呢?
我们首先定义一个Dog类:
public class Dog { private int age; private String name; public void setAge( int age ){ this.age = age; } public void setName( String name ){ this.name = name; } }
注入Dog对象
@Bean public Dog dog(){ Dog dog = new Dog(); dog.setName("旺旺"); return dog; }
之后从ApplicationContext中拿取Bean;
@RequestMapping("/test") @RestController public class test { @Resource(name = "dog") private Dog dog; @Autowired private ApplicationContext applicationContext; @RequestMapping("u1") public String test1(){ Dog bean = (Dog) applicationContext.getBean(Dog.class); return "从Context中拿取Bean = "+bean.toString()+"原生Dog"+dog.toString(); } }
下面就是我们拿到额结果
无论我们刷新多少次浏览器的得到的都是一样啊的结果,这就说明,我们在ApplicationContext中取到的bean和最开始注入的bean是同一个bean,由此大家可以想到,这里bean应该是注入一次,因此每次从ApplicationContext中取出的bean都是一样的,由此可以推断出,bean是单例模式,但其实bean还有其他的模式,只不过bean默认是单利的模式分别为:
在Spring中⽀持6种作⽤域,后4种在Spring MVC环境才⽣效
1. singleton:单例作⽤域
2. prototype:原型作⽤域(多例作⽤域)
3. request:请求作⽤域
4. session:会话作⽤域
5. Application: 全局作⽤域
6. websocket:HTTP WebSocket 作⽤域
singleton 每个Spring IoC容器内同名称的bean只有⼀个实例(单例)(默认)
prototype 每次使⽤该bean时会创建新的实例(⾮单例)
request 每个HTTP 请求⽣命周期内, 创建新的实例(web环境中, 了解)
session 每个HTTP Session⽣命周期内, 创建新的实例(web环境中, 了解)
application 每个ServletContext⽣命周期内, 创建新的实例(web环境中, 了解)
websocket 每个WebSocket⽣命周期内, 创建新的实例(web环境中, 了解)
在bean的生命周期中默认的就是singleton(单利作用域),也就是从头到尾只会注入一个bean不会发生改变。
修改bean的生命周期有两种方式,一种是使用@Scope(“具体的模式名称”)如 @Scope("singleton")这就代表着单例模式,还有一种方式也是使用@Scope注解但是()里的内容不一样例如:@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)。
还有一些注解也可以直接使用如:@RequestScope(请求作用区) @SessionScope(会话作用域) @ApplicationScope(全局作用域)。
至于最后一种HTTP WebSocket 作⽤域,我们在这里无法进行演示,就不在此进行演示了。
prototype: 原型作用域又叫做多利作用域。
如果我们想要设置多利模式可以按一下方式设置有两种也就是分别为@Scope("prototype")和@Scope(ConfigurableBeanFactory.SCOPE.PEOTOTYPE);
接下来我们开看一下它的效果:
这分别是两次不同的结果,我们可以看到,这两次云街道结果中从Context中拿到的数据并不相同, 由此我们就可以看到,每一次实例Bean都会创建一个新的实例,而原生的bean只会创建一次。这就是prototype的作用效果。
request请求作用域,作用效果就是在每一次HTTP生命周期内。都会创建一个Bean,接下来我们就来演示一下:
@Bean @RequestScope public Dog requestDog(){ return new Dog(); }
以上分别是两次不同的结果 ,我们可以看到,无论是在ApplicationContext找那个还是在原生的bean中都发生了变化。这是因为每个HTTP请求是独立的,因此每次从ApplicationContext中国拿到的Bean也是不一样的。这就意味着不同的请求,相同的Bean会是不同的实例。
Session 作用域:想必对于Session大家都非常熟悉了,简单来说就是一个Spring容器会在HTTP绘画中,创建并维护一个Bean实例,每当用户发送新的会话时,Spring就会创建一个新的bean,我们可以不同的浏览器实现这一现象
这是两个不同浏览器的不同结果,如果我们刷新浏览器会发现,结果不会发生任何的变化,这是因为,一个会话一旦创建除非手动销毁不然就会一直存在。
Application: 全局作⽤域
这分别是两个不同浏览器的结果,这两个浏览器的结果是一致的,这是因为 Application全局作用域是在每个ServletContext⽣命周期(ServletContext
的生命周期是指在 Java EE(Jakarta EE)Web 应用程序中,ServletContext
对象的创建、使用和销毁的整个过程)内, 创建新的实例。简单来说也就是只要后端不关闭无论前端如何访问,都是相同的结果。除非当 Web 应用程序停止、被卸载或服务器关闭时,Web 容器会调用 ServletContext
的销毁过程。在这个阶段,容器将调用所有 Servlet 的 destroy()
方法,释放资源并执行清理操作。此后,ServletContext
实例将被销毁。