来源 | 说明 |
---|---|
sigleton | 默认 Spring Bean 作用域,一个 BeanFactory 有且仅有一个实例 |
prototype | 原型作用域,每次依赖查找和依赖注入生成新 Bean 对象 |
request | 将 Spring Bean 存储在 ServletRequest 上下文中 |
session | 将 Spring Bean 存储在 HttpSession 中 |
application | 将 Spring Bean 存储在 ServletContext 中 |
主要是 Singleton 和 Prototype 这两种,其余的是在后续版本中才加入的,并且在 BeanDefinition 中也只有 sigleton 和 prototype 两种作用域的定义
8.1 Singleton在一定范围内是唯一的,Spring 中就是在一个 BeanFactory 内部是唯一的
8.2 Prototype@Configuration @PropertySource("default.properties") public class BeanScopeDemo { @Value("${usr.name:default}") private String name; @Value("${usr.age:28}") private int age; @Bean public User singletonUser() { return new User(this.name, this.age); } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public User prototypeUser() { return new User(this.name, this.age); } public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(BeanScopeDemo.class); context.refresh(); System.out.println(context.getBean("singletonUser", User.class) == context.getBean("singletonUser", User.class)); System.out.println(context.getBean("prototypeUser", User.class) == context.getBean("prototypeUser", User.class)); context.close(); } } public class User implements BeanNameAware { private transient String beanName; private String name; private int age; public User() { } public User(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } @PostConstruct public void init() { System.out.println("用户 Bean[" + beanName + "]初始化..."); } @PreDestroy public void destroy() { System.out.println("用户 Bean[" + beanName + "]销毁..."); } @Override public void setBeanName(String name) { this.beanName = name; } } // 运行结果: 用户 Bean[singletonUser]初始化... true 用户 Bean[prototypeUser]初始化... 用户 Bean[prototypeUser]初始化... false 用户 Bean[singletonUser]销毁...
Spring 容器没有办法管理 protoType Bean 完整的生命周期,也没有办法记录实例的存在。销毁回调方法将不会执行,可以利用 BeanPostProcessor 进行清扫工作。
结论:
-
Singleton Bean 无论依赖查找还是依赖注入,均为同一个对象,Prototype Bean 无论依赖查找还是依赖注入,均为新生成对象
-
如果依赖注入集合类型对象,Singleton Bean 和 Prototype Bean 均会存在一个且只有一个
-
无论是 Singleton 还是 Prototype Bean 均会执行初始化方法回调,不过仅 Singleton Bean 会执行销毁方法回调
配置
-
XML——
-
Java 注解——@RequestScope 或 @Scope(WebApplicationContext.SCOPE_REQUEST)
实现
-
API——RequestScope
对象会被代理,页面渲染时是新对象,通过 Model 传递给 JSP 的对象每次都是新的,但是代理对象是不变的
8.4 Session配置
-
XML——
-
Java 注解——@SessionScope 或 @Scope(WebApplicationContext.SCOPE_SESSION)
实现
-
API——SessionScope
对象会被代理,页面渲染时是新对象,通过 Model 传递给 JSP 的对象在每次会话中都是相同的,不同会话中不同,但是代理对象是不变的
8.5 Application配置
-
XML——
-
Java 注解——@ApplicationScope 或 @Scope(WebApplicationContext.SCOPE_APPLICATION)
实现
-
API——ServletContextScope
JSP EL 变量搜索路径 page -> request -> session -> application(ServletContext)
ApplicationContext 作用域其实就是将 Bean 放到 ServletContext 中进行存储,因此我们不必使用 Model 进行数据的传输,可以直接在 JSP 页面中使用 Application 作用域的bean
8.6 自定义 Bean 作用域-
实现 Scope
-
org.springfamework.beans.factory.config.Scope
-
-
注册 Scope
-
API——org.springframework.beans.factory.config.ConfigurableBeanFactory#registerScope
-
配置
-
8.7.1 Spring 内建的 Bean 作用域有几种?
六种:sigleton、prototype、request、session、application 以及 websocket
从设计模式:单例和原生(原型)
从web模式:request、session、application、websocket
8.7.2 singleton Bean 是否在一个应用中是唯一的
不是,只是在一个 BeanFactory 中是唯一的,整个应用可能包含多个应用上下文(层次上下文),不同上下文中互不影响
同样的,一个静态字段在 JVM 中是否唯一?不是唯一的,静态字段相对于 ClassLoader 唯一,但是一个 JVM 进程可能包含多个 ClassCloader
8.7.3 application 作用域 Bean 是否能被其他方案替代
是可以的,实际上,application bean 与 singleton bean 没有本质区别,无非是在某处进行了存储,跟 Ioc 容器中的 bean 是同一个
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)