一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 如何在Spring中自定義scope的方法示例

如何在Spring中自定義scope的方法示例

2021-07-16 14:15waylau Java教程

這篇文章主要介紹了如何在Spring中自定義scope的方法示例,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

大家對于 spring 的 scope 應該都不會默認。所謂 scope,字面理解就是“作用域”、“范圍”,如果一個 bean 的 scope 配置為 singleton,則從容器中獲取 bean 返回的對象都是相同的;如果 scope 配置為prototype,則每次返回的對象都不同。

一般情況下,spring 提供的 scope 都能滿足日常應用的場景。但如果你的需求極其特殊,則本文所介紹自定義 scope 合適你。

spring 內置的 scope

默認時,所有 spring bean 都是的單例的,意思是在整個 spring 應用中,bean的實例只有一個。可以在 bean 中添加 scope 屬性來修改這個默認值。scope 屬性可用的值如下:

 

范圍 描述
singleton 每個 spring 容器一個實例(默認值)
prototype 允許 bean 可以被多次實例化(使用一次就創建一個實例)
request 定義 bean 的 scope 是 http 請求。每個 http 請求都有自己的實例。只有在使用有 web 能力的 spring 上下文時才有效
session 定義 bean 的 scope 是 http 會話。只有在使用有 web 能力的 spring applicationcontext 才有效
application 定義了每個 servletcontext 一個實例
websocket 定義了每個 websocket 一個實例。只有在使用有 web 能力的 spring applicationcontext 才有效

 

如果上述 scope 仍然不能滿足你的需求,spring 還預留了接口,允許你自定義 scope。

scope 接口

org.springframework.beans.factory.config.scope接口用于定義scope的行為:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package org.springframework.beans.factory.config;
 
import org.springframework.beans.factory.objectfactory;
import org.springframework.lang.nullable;
 
public interface scope {
 
 object get(string name, objectfactory<?> objectfactory);
 
 @nullable
 object remove(string name);
 
 void registerdestructioncallback(string name, runnable callback);
 
 @nullable
 object resolvecontextualobject(string key);
 
 @nullable
 string getconversationid();
 
}

一般來說,只需要重新 get 和 remove 方法即可。

自定義線程范圍內的scope

現在進入實戰環節。我們要自定義一個spring沒有的scope,該scope將bean的作用范圍限制在了線程內。即,相同線程內的bean是同個對象,跨線程則是不同的對象。

1. 定義scope

要自定義一個spring的scope,只需實現 org.springframework.beans.factory.config.scope接口。代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.waylau.spring.scope;
 
import java.util.hashmap;
import java.util.map;
 
import org.springframework.beans.factory.objectfactory;
import org.springframework.beans.factory.config.scope;
 
/**
 * thread scope.
 *
 * @since 1.0.0 2019年2月13日
 * @author <a href="https://waylau.com" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >way lau</a>
 */
public class threadscope implements scope {
 
 private final threadlocal<map<string, object>> threadloacal = new threadlocal<map<string, object>>() {
 @override
 protected map<string, object> initialvalue() {
  return new hashmap<string, object>();
 }
 };
 
 public object get(string name, objectfactory<?> objectfactory) {
 map<string, object> scope = threadloacal.get();
 object obj = scope.get(name);
 
 // 不存在則放入threadlocal
 if (obj == null) {
  obj = objectfactory.getobject();
  scope.put(name, obj);
  
  system.out.println("not exists " + name + "; hashcode: " + obj.hashcode());
 } else {
  system.out.println("exists " + name + "; hashcode: " + obj.hashcode());
 }
 
 return obj;
 }
 
 public object remove(string name) {
 map<string, object> scope = threadloacal.get();
 return scope.remove(name);
 }
 
 public string getconversationid() {
 return null;
 }
 
 public void registerdestructioncallback(string arg0, runnable arg1) {
 }
 
 public object resolvecontextualobject(string arg0) {
 return null;
 }
 
}

在上述代碼中,threadloacal用于做線程之間的數據隔離。換言之,threadloacal實現了相同的線程相同名字的bean是同一個對象;不同的線程的相同名字的bean是不同的對象。

同時,我們將對象的hashcode打印了出來。如果他們是相同的對象,則hashcode是相同的。

2. 注冊scope

定義一個appconfig配置類,將自定義的scope注冊到容器中去。代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.waylau.spring.scope;
 
import java.util.hashmap;
import java.util.map;
 
import org.springframework.beans.factory.config.customscopeconfigurer;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.componentscan;
import org.springframework.context.annotation.configuration;
 
/**
 * app config.
 *
 * @since 1.0.0 2019年2月13日
 * @author <a href="https://waylau.com" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >way lau</a>
 */
@configuration
@componentscan
public class appconfig {
 
 @bean
 public static customscopeconfigurer customscopeconfigurer() {
 customscopeconfigurer customscopeconfigurer = new customscopeconfigurer();
 
 map<string, object> map = new hashmap<string, object>();
 map.put("threadscope", new threadscope());
 
 // 配置scope
 customscopeconfigurer.setscopes(map);
 return customscopeconfigurer;
 }
}

“threadscope”就是自定義threadscope的名稱。

3. 使用scope

接下來就根據一般的scope的用法,來使用自定義的scope了。代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.waylau.spring.scope.service;
 
import org.springframework.context.annotation.scope;
import org.springframework.stereotype.service;
 
/**
 * message service impl.
 *
 * @since 1.0.0 2019年2月13日
 * @author <a href="https://waylau.com" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >way lau</a>
 */
@scope("threadscope")
@service
public class messageserviceimpl implements messageservice {
 
 public string getmessage() {
 return "hello world!";
 }
 
}

其中@scope("threadscope")中的“threadscope”就是自定義threadscope的名稱。

4. 定義應用入口

定義spring應用入口:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.waylau.spring.scope;
 
import org.springframework.context.applicationcontext;
import org.springframework.context.annotation.annotationconfigapplicationcontext;
 
import com.waylau.spring.scope.service.messageservice;
 
/**
 * application main.
 *
 * @since 1.0.0 2019年2月13日
 * @author <a href="https://waylau.com" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >way lau</a>
 */
public class application {
 
 public static void main(string[] args) {
 @suppresswarnings("resource")
 applicationcontext context =
      new annotationconfigapplicationcontext(appconfig.class);
 
 messageservice messageservice = context.getbean(messageservice.class);
 messageservice.getmessage();
 
 messageservice messageservice2 = context.getbean(messageservice.class);
 messageservice2.getmessage();
 
 }
 
}

運行應用觀察控制臺輸出如下:

not exists messageserviceimpl; hashcode: 2146338580
exists messageserviceimpl; hashcode: 2146338580

輸出的結果也就驗證了threadscope“相同的線程相同名字的bean是同一個對象”。

如果想繼續驗證threadscope“不同的線程的相同名字的bean是不同的對象”,則只需要將application改造為多線程即可。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package com.waylau.spring.scope;
 
import java.util.concurrent.completablefuture;
import java.util.concurrent.executionexception;
 
import org.springframework.context.applicationcontext;
import org.springframework.context.annotation.annotationconfigapplicationcontext;
 
import com.waylau.spring.scope.service.messageservice;
 
/**
 * application main.
 *
 * @since 1.0.0 2019年2月13日
 * @author <a href="https://waylau.com" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >way lau</a>
 */
public class application {
 
 public static void main(string[] args) throws interruptedexception, executionexception {
 @suppresswarnings("resource")
 applicationcontext context =
  new annotationconfigapplicationcontext(appconfig.class);
 
 completablefuture<string> task1 = completablefuture.supplyasync(()->{
      //模擬執行耗時任務
      messageservice messageservice = context.getbean(messageservice.class);
  messageservice.getmessage();
 
  messageservice messageservice2 = context.getbean(messageservice.class);
  messageservice2.getmessage();
      //返回結果
      return "result";
    });
 
 completablefuture<string> task2 = completablefuture.supplyasync(()->{
      //模擬執行耗時任務
      messageservice messageservice = context.getbean(messageservice.class);
  messageservice.getmessage();
 
  messageservice messageservice2 = context.getbean(messageservice.class);
  messageservice2.getmessage();
      //返回結果
      return "result";
    });
 
 task1.get();
 task2.get();
 
 }
}

觀察輸出結果;

not exists messageserviceimpl; hashcode: 1057328090
not exists messageserviceimpl; hashcode: 784932540
exists messageserviceimpl; hashcode: 1057328090
exists messageserviceimpl; hashcode: 784932540

上述結果驗證threadscope“相同的線程相同名字的bean是同一個對象;不同的線程的相同名字的bean是不同的對象”

源碼

見 的 s5-ch02-custom-scope-annotation項目。

https://github.com/waylau/spring-5-book上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://my.oschina.net/waylau/blog/3009991

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 午夜伦理yy44008影院 | 夫妻性生活影院 | 四虎最新永久免费视频 | 婷婷久久热99在线精品 | 美女脱了内裤打开腿让人桶网站o | 国产精品久久久久影视不卡 | 亚洲精品久久久打桩机 | 免费视频网 | 俄罗斯男男激情1069gay | 欧美se图| 小鸟酱在线看 | 无码AV精品一区二区三区 | 水蜜桃一二二区视在线 | 手机看片一区二区 | 西西人体大胆啪啪私拍色约约 | 免费看一级 | 青青国产成人久久激情91麻豆 | 亚洲码和乱人伦中文一区 | 秋霞啪啪片 | 欧美综合亚洲图片综合区 | 狠狠躁夜夜躁人人爽天天miya | 日本大尺度动漫在线观看缘之空 | xxxxxx日本处大片免费看 | 国产在线观看91精品一区 | 吻戏辣妞范1000免费体验 | 午夜片无码区在线观看 | 国产98在线| 国产资源免费观看 | 日日摸日日添日日透 | 操爽| 国产自产2023最新麻豆 | 毛片在线播放a | 韩剧消失的眼角膜免费完整版 | 十八女下面流水不遮免费 | 日本嫩交| 午夜影院网站 | 日韩中文字幕网站 | 四虎免费永久观看 | 玩50岁四川熟女大白屁股直播 | 国产欧美日韩在线不卡第一页 | 手机在线观看国产精选免费 |