网站建设对企业的好处深圳市福田建设局网站

当前位置: 首页 > news >正文

网站建设对企业的好处,深圳市福田建设局网站,杭州h5建站,大连建设工程设计院有限公司网站目录 一、spring当中有哪些scope 二、scope初始化与销毁演示 2.1 scope的初始化
2.2 scope的销毁 三、scope失效及其解决方案
3.1 scope失效演示 3.2 scope失效解决方案一#xff1a;Lazy
3.3 scope失效解决方案二#xff1a;设置proxyMode属性 3.4 scope失效解决…目录 一、spring当中有哪些scope 二、scope初始化与销毁演示 2.1 scope的初始化  2.2 scope的销毁 三、scope失效及其解决方案  3.1 scope失效演示 3.2 scope失效解决方案一Lazy  3.3 scope失效解决方案二设置proxyMode属性 3.4 scope失效解决方案三ObjectFactory 3.5  scope失效解决方案四ApplicationContext容器 3.6 总结 一、spring当中有哪些scope 我使用的spring版本是5.3.10其中scope有五种 singleton从spring中获取bean时每次获取的是同一个bean prototype从spring中获取bean时每次获取的是新的bean request生成的bean存活于request域中生命周期也与request相同 session生成的bean存活于session域中生命周期也与session相同 application生成的bean存活于application域中生命周期也与application相同spring中的application指的是servletContext 二、scope初始化与销毁演示 2.1 scope的初始化  主启动类 SpringBootApplication public class A08 {public static void main(String[] args) {SpringApplication.run(A08.class, args);} } 主启动类启动后就会扫描到下面的三个bean Scope(request) Component public class BeanForRequest {private static final Logger log LoggerFactory.getLogger(BeanForRequest.class);PreDestroypublic void destroy() {log.debug(destroy);} } Scope(session) Component public class BeanForSession {private static final Logger log LoggerFactory.getLogger(BeanForSession.class);PreDestroypublic void destroy() {log.debug(destroy);} } Scope(application) Component public class BeanForApplication {private static final Logger log LoggerFactory.getLogger(BeanForApplication.class);PreDestroypublic void destroy() {log.debug(destroy);} } 这三个bean在controller中被用到 RestController public class MyController {//MyController是单例单例去使用其他的域都要加Lazy否则会失效LazyAutowiredprivate BeanForRequest beanForRequest;LazyAutowiredprivate BeanForSession beanForSession;LazyAutowiredprivate BeanForApplication beanForApplication;GetMapping(value /test, produces text/html)public String test(HttpServletRequest request, HttpSession session) {ServletContext sc request.getServletContext();String sb ul li request scope: beanForRequest /li li session scope: beanForSession /li li application scope: beanForApplication /li /ul;return sb;} } 打开不同的浏览器, 刷新 http://localhost:8080/test 即可查看效果。如果 jdk 8, 运行时请添加 –add-opens java.base/java.langALL-UNNAMED 打开一个浏览器例如Chrome可以发现每次刷新都可以看到request域的bean不一样说明每次创建的是新的beanrequest的bean会在请求结束后销毁。 再打开一个浏览器例如edge可以发现会话域的bean也不同是因为每个浏览器都会创建自己的会话。 打开不同的浏览器也能看到request和session的bean不相同是因为每个浏览器都有自己的请求和会话域而application的bean时相同的因为他们对应的是同一个web应用程序 2.2 scope的销毁 singleton容器启动时创建未设置延迟容器关闭时销毁 prototype每次使用时创建不会自动销毁需要调用DefaultListableBeanFactory.destroyBean(bean) 销毁 request每次请求用到此 bean 时创建请求结束时销毁 session每个会话用到此 bean 时创建会话结束时销毁 applicationweb 容器用到此 bean 时创建容器停止时销毁 在浏览器中每次刷新我们都可以看到控制台打印出了beanForRequest的销毁方法这是因为每次刷新都代表着一个请求结束了session销毁时间默认为30min为了方便演示我们在application.properties文件中设置 server.servlet.session.timeout10s 这样session就可以在1min后自动销毁了spring内部设置session销毁时间低于1min就视为1min这篇文章剖析了这部分源码SpringBoot设置Session失效时间 - 简书我们可以在控制台上看到session销毁的日志 三、scope失效及其解决方案  3.1 scope失效演示 以单例注入多例为例单例注入其他类型的scope也是同理先看看主启动类 ComponentScan(com.itheima.a08.sub) public class A08_1 {private static final Logger log LoggerFactory.getLogger(A08_1.class);public static void main(String[] args) {AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(A08_1.class);E e context.getBean(E.class);log.debug({}, e.getF1().getClass());log.debug({}, e.getF1());log.debug({}, e.getF1());log.debug({}, e.getF1());context.close();} } 在主启动类中我们先通过getBean方法拿到E的对象再通过get方法拿到e中注入的f1对象。E并没有加prototype注解所以默认是个单例而f1是个多例。 Component public class E {Autowiredprivate F1 f1;public F1 getF1() {return f1;} } Scope(prototype) Component public class F1 { } 那么问题来了我们在主启动类中多调用几次每次返回的f1对象是同一个对象还是不同对象我们既然将F1标注为多例自然是期望返回不同对象的。 然而运行可得每次返回的都是同一对象  原因是对于单例对象来讲依赖注入仅发生一次后续再没有发生依赖注入E再没有用到多例的F1因此E用的始终是第一次依赖注入的F1。 3.2 scope失效解决方案一Lazy  我们在成员变量或者使用的方法上加上Lazy注解Lazy能够帮助我们生成代理对象这样代理对象虽然还是同一个但当每次使用代理对象的任意方法时由代理创建新的f1对象。  Component public class E {LazyAutowiredprivate F1 f1;public F1 getF1() {return f1;} } 运行发现每次生成的bean已经不一样了。我们也打印一下e.getF1().getClass看看生成的F1的真实类型可以看到并不是F1而是代理增强的类。 3.3 scope失效解决方案二设置proxyMode属性 我们还可以在被调用的多例类上设置 proxyMode 属性我们用F2来演示这个解决办法 Scope(value prototype, proxyMode ScopedProxyMode.TARGET_CLASS) Component public class F2 { } 这个方法的本质也是生成代理。运行后可以看到生成的bean也不一样了获取到的F2的真实类型也是代理增强的类。  3.4 scope失效解决方案三ObjectFactory 我们可以在E中注入的时候将F声明为 ObjectFactory 类型这样每次获取的时候都由工厂生成不同的F。我们用F3来演示这个解决办法 Component public class E {Autowiredprivate ObjectFactoryF3 f3;public F3 getF3() {return f3.getObject();} } Scope(prototype) Component public class F3 { } 3.5  scope失效解决方案四ApplicationContext容器 直接实现容器利用容器的getBean方法来获取F多例bean。我们用F4来演示 Component public class E {Autowiredprivate ApplicationContext context;public F4 getF4() {return context.getBean(F4.class);} } Scope(prototype) Component public class F4 { } 3.6 总结 虽然上述四种方法各不相同但理念基本相同都是延迟其他scope bean的获取。他们都是不直接获取多例而是在中间加一个对象通过这个对象等到运行时再去获取多例bean  更推荐使用BeanFactory 或 ApplicationContext因为更加简洁且不像代理一样会造成一定的性能损耗。