一、@Scope
概念:简单说就是对象在spring容器(IOC容器)中的生命周期,也可以理解为对象在spring容器中的创建方式,在不指定@Scope的情况下,所有的bean都是单实例的bean,而且是饿汉加载(容器启动实例就创建好了) 。
具体创建方式有如下五种方式:
1、singleton 单实例(默认)
所有引用此bean都是单一实例,从容器启动到第一次被请求而实例化开始,只要容器不销毁或退出,该类型的bean的单一实例就会一直存活。
public class SingletonBert {
public SingletonBert() {
System.out.println("创建构造器SingletonBert");
}
}
@Bean
public SingletonBert singletonBert() {
return new SingletonBert();
}
懒加载@Lazy(主要针对单实例的bean 容器启动的时候,不创建对象,在第一次使用的时候才会创建该对象)
@Bean
@Lazy
public SingletonLazyBert singletonLazyBert() {
return new SingletonLazyBert();
}
2、prototype 多实例
spring容器会每次都重新生成一个新的对象给请求方,容器就不在拥有当前对象的引用,请求方需要自己负责当前对象后继生命周期的管理工作,包括该对象的销毁。
public class PrototypeBert {
public PrototypeBert() {
System.out.println("创建构造器PrototypeBert");
}
}
@Bean
@Scope(value = "prototype")
public PrototypeBert prototypeBert() {
return new PrototypeBert();
}
3、request 同一次请求
对于web应用来说,XmlWebApplicationContext 会为每个HTTP请求创建一个全新的RequestPrecessor对象,当请求结束后,该对象的生命周期即告结束。
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode= ScopedProxyMode.INTERFACES)
public class RequestBert implements IRequestBert {
public RequestBert() {
System.out.println("创建构造器RequestBert" + UUID.randomUUID());
}
}
public interface IRequestBert {
}
4、 session 同一个会话级别
Spring容器会为每个独立的session创建属于自己的全新的UserPreferences实例,比request scope的bean会存活更长的时间。
@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode= ScopedProxyMode.INTERFACES)
public class SessionBert implements ISessionBert {
public SessionBert() {
System.out.println("创建构造器SessionBert" + UUID.randomUUID());
}
}
5、application 同一个应用级别
global session只有应用在基于porlet的web应用程序中才有意义,它映射到porlet的global范围的session,如果普通的servlet的web 应用中使用了这个scope,容器会把它作为普通的session的scope对待。
@Component
@Scope(value = WebApplicationContext.SCOPE_APPLICATION, proxyMode= ScopedProxyMode.INTERFACES)
public class ApplicationBert implements IApplicationBert {
public ApplicationBert() {
System.out.println("创建构造器ApplicationBert" + UUID.randomUUID());
}
}
二、测试
1、二种配置层面的bean作用域
@Configuration
public class ScopeMain {
@Bean
public SingletonBert singletonBert() {
return new SingletonBert();
}
@Bean
@Lazy
public SingletonLazyBert singletonLazyBert() {
return new SingletonLazyBert();
}
@Bean
@Scope(value = "prototype")
public PrototypeBert prototypeBert()
return new PrototypeBert();
}
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ScopeMain.class);
System.out.println(ctx.getBean("prototypeBert"));
System.out.println(ctx.getBean("singletonLazyBert"));
}
}
运行结果:
创建构造器SingletonBert
创建构造器PrototypeBert
com.bert.scope.PrototypeBert@17776a8
创建构造器SingletonLazyBert
com.bert.scope.SingletonLazyBert@69a10787
2、三种Web范围的bean作用域
@RestController
public class HelloController {
@Autowired
private IRequestBert requestBert;
@Autowired
private ISessionBert sessionBert;
@Autowired
private IApplicationBert applicationBert;
@RequestMapping("/hello")
public String hello() {
System.out.println("requestBert:" + requestBert);
System.out.println("sessionBert:" + sessionBert);
System.out.println("applicationBert:" + applicationBert);
return "Hello bert!";
}
}
1、同一请求:
创建构造器RequestBert2c4ee25f-3ba1-460e-8d33-c1eb35b33dcf
requestBert:com.bert.scope.RequestBert@4d59246b
创建构造器SessionBertd7f7ea3b-597f-4d4d-b34c-89ce3d246b17
sessionBert:com.bert.scope.SessionBert@13bc37cc
创建构造器ApplicationBerta515c69e-832c-41c4-bdd4-269e4638d40f
applicationBert:com.bert.scope.ApplicationBert@fce0c19
2、同一会话:
创建构造器RequestBert478ef2b0-f69f-4338-b7e9-9d830f549264
requestBert:com.bert.scope.RequestBert@2b247288
sessionBert:com.bert.scope.SessionBert@13bc37cc
applicationBert:com.bert.scope.ApplicationBert@fce0c19
3、不同会话,同一应用:
创建构造器RequestBert049c3ae7-edc0-4037-aa30-0d28257acb2c
requestBert:com.bert.scope.RequestBert@5ebb8002
创建构造器SessionBert8d0d5d83-8250-4195-8f08-7a0a8bebb3a0
sessionBert:com.bert.scope.SessionBert@507c65a5
applicationBert:com.bert.scope.ApplicationBert@fce0c19
黄色:request级别,绿色:session级别,红色:application级别
request每次都是一个新对象
session 同一个会话下的请求都是一个对象
application 同一个应用下的都是一个对象