我们用的最多的就是单例singleton了,这个就不再描述
prototype
原型,即我们讲的多例。spring用的属性是注入的方式,即时定义bean的作用域为原型,属性的引用也不会变,也就达不到想要的多例效果。那么怎样才是使用原型的正确方式呢?
准备Bean
@Component
@Scope("prototype")
public class F1 {
}
@Component
@Scope("prototype")
public class F2 {
}
@Component
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class F3 {
}
@Component
@Scope("prototype")
public class F4 {
}
使用多例
@Getter
@Component
public class E {
@Autowired
private F1 f1;
@Lazy
@Autowired
private F2 f2;
@Autowired
private F3 f3;
@Autowired
private ObjectFactory<F4> f4;
@Autowired
private ApplicationContext applicationContext;
public F1 getF12() {
return applicationContext.getBean(F1.class);
}
public F4 getF4() {
return f4.getObject();
}
}
验证
ConfigurableApplicationContext applicationContext = SpringApplication.run(TestScope02.class, args);
E e = applicationContext.getBean(E.class);
System.out.println("==========F1========");
for (int i = 0; i < 3; i++) {
// F1对象都是同一个 多例无效果
System.out.println(e.getF1());
}
System.out.println("==========F1========");
System.out.println("==========F2========");
for (int i = 0; i < 3; i++) {
// @Lazy F2对象都不相同 多例生效
System.out.println(e.getF2());
}
System.out.println("==========F2========");
System.out.println("==========F3========");
for (int i = 0; i < 3; i++) {
// proxyMode = ScopedProxyMode.TARGET_CLASS F3对象都不相同 多例生效
System.out.println(e.getF3());
}
System.out.println("==========F3========");
System.out.println("==========F4========");
for (int i = 0; i < 3; i++) {
// ObjectFactory 对象都不相同 多例生效
System.out.println(e.getF4());
}
System.out.println("==========F4========");
System.out.println("==========F12========");
for (int i = 0; i < 3; i++) {
// ApplicationContext 对象都不相同 多例生效
System.out.println(e.getF12());
}
System.out.println("==========F12========");
applicationContext.close();
request、session、application
准备bean
@Scope("request")
@Component
public class Bean4Request {
@PreDestroy
public void destroy() {
// request请求结束立即销毁
System.err.println("Bean4Request destroy");
}
}
@Scope("session")
@Component
public class Bean4Session {
@PreDestroy
public void destroy() {
System.err.println("Bean4Session destroy");
}
}
@Scope("application")
@Component
public class Bean4Application {
@PreDestroy
public void destroy() {
System.err.println("Bean4Application destroy");
}
}
验证
@RestController
public class TestController {
/**
* 单例Bean引入非单例Bean需要添加@Lazy注解(还有其它方式)
* 否则引入的对象仍表现为单例
*/
@Lazy
@Autowired
private Bean4Request bean4Request;
@Lazy
@Autowired
private Bean4Session bean4Session;
@Lazy
@Autowired
private Bean4Application bean4Application;
@GetMapping(value = "/test")
public String test() {
return "<ul>" +
"<li> request scope:" + bean4Request + "</li>" +
"<li> session scope:" + bean4Session + "</li>" +
"<li> application scope:" + bean4Application + "</li>" +
"</ul>";
}
}