Spring原理分析-Scope
2022-04-14 本文已影响0人
石头耳东
零、本文纲要
一、Scope
1、Scope类型
2、基础准备与演示
二、Scope失效
1、基础准备与演示
2、失效原因及处理
3、总结
一、Scope
1、Scope类型
singleton, prototype, request, session, application
2、基础准备与演示
- ① 编写各种Scope的Bean
request类型,如下:
@Scope("request")
@Component
public class BeanForRequest {
private static final Logger log = LoggerFactory.getLogger(BeanForRequest.class);
@PreDestroy
public void destroy(){
log.debug("BeanForRequest DESTROY");
}
}
session类型,如下:
@Scope("session")
@Component
public class BeanForSession {
private static final Logger log = LoggerFactory.getLogger(BeanForSession.class);
@PreDestroy
public void destroy(){
log.debug("BeanForSession DESTROY");
}
}
application类型,如下:
@Scope("application")
@Component
public class BeanForApplication {
private static final Logger log = LoggerFactory.getLogger(BeanForApplication.class);
@PreDestroy
public void destroy(){
log.debug("BeanForApplication DESTROY");
}
}
- ② 编写Controller类
@RestController
public class MyController {
@Lazy
@Autowired
private BeanForRequest beanForRequest;
@Lazy
@Autowired
private BeanForSession beanForSession;
@Lazy
@Autowired
private BeanForApplication beanForApplication;
@GetMapping(value = "/test", produces = "text/html")
public String test(HttpServletRequest request, HttpSession session){
ServletContext context = request.getServletContext();
String resp = "<ul>" +
"<li>" + "REQUEST SCOPE:" + beanForRequest + "</li>" +
"<li>" + "SESSION SCOPE:" + beanForSession + "</li>" +
"<li>" + "APPLICATION SCOPE:" + beanForApplication + "</li>" +
"</ul>";
return resp;
}
}
- ③ 编写启动类
@SpringBootApplication
public class Demo08 {
public static void main(String[] args) {
SpringApplication.run(Demo08.class, args);
}
}
- ④ 测试
二、Scope失效
1、基础准备与演示
- ① 多例Bean
编写F1,其Scope为prototype多例,如下:
@Scope("prototype")
@Component
public class F1 {
}
- ② Bean属性管理多例Bean
编写E,其内部注入F1,如下:
@Component
public class E {
// @Lazy
@Autowired
private F1 f1;
public F1 getF1(){return f1;}
}
- ③ 测试类
@ComponentScan("com.stone.demo08.entity")
public class ApplicationDemo {
private static final Logger log = LoggerFactory.getLogger(ApplicationDemo.class);
public static void main(String[] args) {
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(ApplicationDemo.class);
E e = context.getBean(E.class);
log.debug("{}", e.getF1());
log.debug("{}", e.getF1());
log.debug("{}", e.getF1());
context.close();
}
}
多例失效情形.png
2、失效原因及处理
- ① 失效原因
单例E被创建时,完成了F属性的注入。此后调用get方法,得到的始终是只创建一次时注入的F对象。
- ② 处理方法
Ⅰ 添加@Lazy注解
添加@Lazy注解.png@Lazy注解会生成目标对象的代理对象,代理对象虽然还是同一个,但当每次使用代理对象的任意方法时,由代理创建新的 f 对象。
使用代理对象.pngⅡ 添加proxyMode = ScopedProxyMode.TARGET_CLASS属性
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
@Component
public class F2 {
}
TARGET_CLASS属性.png
Ⅲ 使用ObjectFactory工厂
@Autowired
private ObjectFactory<F3> f3;
public F3 getF3() {
return f3.getObject();
}
使用ObjectFactory工厂.png
Ⅳ 使用ApplicationContext
@Autowired
private ApplicationContext context;
public F4 getF4(){return context.getBean(F4.class);}
使用ApplicationContext.png
3、总结
- ① Scope失效处理方法
Ⅰ @Lazy注解;
Ⅱ @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS);
Ⅲ ObjectFactory工厂;
Ⅳ ApplicationContext。
四种方法的共同特点都是在运行时再去获取多例对象,推迟了其他Scope Bean的获取。
- ② 推荐使用
推荐使用ObjectFactory工厂、ApplicationContext这两种方法,性能更优。
三、结尾
以上即为Spring原理分析-Scope的全部内容,感谢阅读。