在 Spring IoC 容器中具有以下几种作用域:
- singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例,适用于无状态bean;
- prototype:原型模式,`每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例,适用于有状态的Bean; ----
demo
环境搭建
定义@Scope(“prototype”)- bean
@Slf4j
@Component
@Scope("prototype")
public class FooService {
@Value("${x.foo}")
private String foo;
public void foo() {
log.info("---foo:{} ,{}", foo, this);
}
@PostConstruct
public void init() {
log.info("---foo:init");
}
public FooService(){
log.info("---foo:construct");
}
@PreDestroy
public void destroy(){
log.warn("---foo:destroy");
}
}
@Slf4j
@Component
@Scope("prototype")
public class BarService {
@Value("${x.bar}")
private String bar;
public void bar() {
log.info("---bar:{} ,{}",bar,this);
}
@PostConstruct
public void init() {
log.info("---bar:init");
}
public BarService(){
log.info("---bar:construct");
}
@PreDestroy
public void destroy(){
log.warn("---bar:destroy");
}
}
定义@Scope(“singleton”)-bean
@Component
@Scope("singleton")
//@Lazy
@Slf4j
public class SingletonService {
public void exec() {
log.info("---singleton:{} ", this);
}
@PostConstruct
public void init() {
log.info("---singleton:init");
}
public SingletonService(){
log.info("---singleton:construct");
}
@PreDestroy
public void destroy(){
log.warn("---singleton:destroy");
}
}
定义bean调用者
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private FooService fooService;
@Autowired
private ApplicationContext applicationContext;
@GetMapping("/refresh")
public String refresh(){
log.info("-------------------------------");
applicationContext.getBean(BarService.class).bar();
fooService.foo();
applicationContext.getBean(SingletonService.class).exec();
return "success";
}
@GetMapping("/shutdown")
public void shutdownContext() {
((ConfigurableApplicationContext) applicationContext).close();
}
}
日志
启动服务时
2022-09-28 13:56:02.035 [main] INFO c.j.e.e.refresh2.service.FooService - ---foo:construct
2022-09-28 13:56:02.038 [main] INFO c.j.e.e.refresh2.service.FooService - ---foo:init
2022-09-28 13:56:02.042 [main] INFO c.j.e.e.r.service.SingletonService - ---singleton:construct
2022-09-28 13:56:02.042 [main] INFO c.j.e.e.r.service.SingletonService - ---singleton:init
- FooService: 虽然
scope为"prototype"
,但是由@Autowired
自动注入,所以在启动容器时就已经通过getBean()
被注入。 - SingletonService:
scope为"singleton"
,启动时便被注入- 可以通过:
@Lazy
来控制是否在容器启动时就初始化。
- 可以通过:
执行"/refresh"请求
- BarService:在执行请求后,方才执行
getBean()
方法,此时BarService才初始化。 — 延迟初始化
2022-09-28 13:56:39.693 [http-nio-8080-exec-1] INFO c.j.e.e.refresh2.TestController - -------------------------------
2022-09-28 13:56:39.694 [http-nio-8080-exec-1] INFO c.j.e.e.refresh2.service.BarService - ---bar:construct
2022-09-28 13:56:39.695 [http-nio-8080-exec-1] INFO c.j.e.e.refresh2.service.BarService - ---bar:init
2022-09-28 13:56:39.695 [http-nio-8080-exec-1] INFO c.j.e.e.refresh2.service.BarService - ---bar:BAR4 ,cn.jhs.e2e.e2eencryptionbiz.refresh2.service.BarService@4cfd6769
2022-09-28 13:56:39.697 [http-nio-8080-exec-1] INFO c.j.e.e.refresh2.service.FooService - ---foo:FOO4 ,cn.jhs.e2e.e2eencryptionbiz.refresh2.service.FooService@2f51409b
2022-09-28 13:56:39.697 [http-nio-8080-exec-1] INFO c.j.e.e.r.service.SingletonService - ---singleton:cn.jhs.e2e.e2eencryptionbiz.refresh2.service.SingletonService@60aec68a
再次执行"/refresh"请求
- BarService:在执行第二次请求后,由spring再次初始化,返回一个新的实例.
2022-09-28 13:57:35.822 [http-nio-8080-exec-2] INFO c.j.e.e.refresh2.TestController - -------------------------------
2022-09-28 13:57:35.823 [http-nio-8080-exec-2] INFO c.j.e.e.refresh2.service.BarService - ---bar:construct
2022-09-28 13:57:35.823 [http-nio-8080-exec-2] INFO c.j.e.e.refresh2.service.BarService - ---bar:init
2022-09-28 13:57:35.823 [http-nio-8080-exec-2] INFO c.j.e.e.refresh2.service.BarService - ---bar:BAR4 ,cn.jhs.e2e.e2eencryptionbiz.refresh2.service.BarService@71f187fc
2022-09-28 13:57:35.823 [http-nio-8080-exec-2] INFO c.j.e.e.refresh2.service.FooService - ---foo:FOO4 ,cn.jhs.e2e.e2eencryptionbiz.refresh2.service.FooService@2f51409b
2022-09-28 13:57:35.823 [http-nio-8080-exec-2] INFO c.j.e.e.r.service.SingletonService - ---singleton:cn.jhs.e2e.e2eencryptionbiz.refresh2.service.SingletonService@60aec68a
执行"/shutdown"
只有@Scope("singleton")
bean ,会执行destory()
方法.
2022-09-28 13:59:31.973 [http-nio-8080-exec-4] WARN c.j.e.e.r.service.SingletonService - —singleton:destroy
结论
Spring
- 不对作用域为prototype的bean的整个生命周期负责:容器在bean
初始化&实例后
,不再负责bean的销毁。 - 作用域为singleton的bean的整个生命周期负责