成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spring Bean的作用域scope你知道多少?如何自定義作用域?

開發 前端
通過@Scope注解可以指定Bean的作用域,默認情況都是單例的(ConfigurableBeanFactory.SCOPE_SINGLETON=singleton),在創建bean實例時就是根據當前定義BeanDefinition中的Scope來做不同的創建。

[[409240]]

環境:spring5.3.3

1 Scope作用

通過@Scope注解可以指定Bean的作用域,默認情況都是單例的(ConfigurableBeanFactory.SCOPE_SINGLETON=singleton)

在創建bean實例時就是根據當前定義BeanDefinition中的Scope來做不同的創建,源碼如下:

  1. protected <T> T doGetBean( 
  2.             String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) 
  3.             throws BeansException { 
  4.   String beanName = transformedBeanName(name); 
  5.   Object bean; 
  6.   // Eagerly check singleton cache for manually registered singletons. 
  7.   Object sharedInstance = getSingleton(beanName); 
  8.   if (sharedInstance != null && args == null) { 
  9.     // other code 
  10.   } else { 
  11.     // other code 
  12.     try { 
  13.       RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 
  14.       checkMergedBeanDefinition(mbd, beanName, args); 
  15.  
  16.       // Guarantee initialization of beans that the current bean depends on
  17.       // other code 
  18.       // Create bean instance. 
  19.       // 根據BeanDefinition中定義的Scope創建實例 
  20.       // 判斷如果是單例 
  21.       if (mbd.isSingleton()) { 
  22.         // 如果是單例Bean會將Bean保存到緩存中singletonObjects   
  23.         sharedInstance = getSingleton(beanName, () -> { 
  24.           try { 
  25.             return createBean(beanName, mbd, args); 
  26.           } catch (BeansException ex) { 
  27.             destroySingleton(beanName); 
  28.             throw ex; 
  29.           } 
  30.         }); 
  31.         bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 
  32.       } 
  33.       // 判斷如果是原型(多例) 
  34.       else if (mbd.isPrototype()) { 
  35.         // It's a prototype -> create a new instance. 
  36.         Object prototypeInstance = null
  37.         try { 
  38.           beforePrototypeCreation(beanName); 
  39.           prototypeInstance = createBean(beanName, mbd, args); 
  40.         } finally { 
  41.           afterPrototypeCreation(beanName); 
  42.         } 
  43.         bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); 
  44.       }  
  45.       else { 
  46.         String scopeName = mbd.getScope(); 
  47.         if (!StringUtils.hasLength(scopeName)) { 
  48.           throw new IllegalStateException("No scope name defined for bean 麓" + beanName + "'"); 
  49.         } 
  50.         Scope scope = this.scopes.get(scopeName); 
  51.         // 當集合中也不存在時拋出異常   
  52.         if (scope == null) { 
  53.           throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); 
  54.         } 
  55.         try { 
  56.           Object scopedInstance = scope.get(beanName, () -> { 
  57.             beforePrototypeCreation(beanName); 
  58.             try { 
  59.               return createBean(beanName, mbd, args); 
  60.             } finally { 
  61.               afterPrototypeCreation(beanName); 
  62.             } 
  63.           }); 
  64.           bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); 
  65.         } catch (IllegalStateException ex) { 
  66.           throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); 
  67.         } 
  68.       } 
  69.     } catch (BeansException ex) { 
  70.       cleanupAfterBeanCreationFailure(beanName); 
  71.       throw ex; 
  72.     } 
  73.   } 
  74.   // other code 
  75.   return (T) bean; 

從上面源碼看到分別判斷是了 是否是 Singleton及Proptotype,如果都不是則會從Map<String, Scope> scopes中獲取。如果當前你配置的@Scope不是singleton及prototype那么從scopes集合中取(這個集合是通過AbstractBeanFactory#registerScope方法進行注冊的,一般我們可以通過
BeanDefinitionRegistryPostProcessor進行注冊),如果集合中也不存在那么就會拋出異常。如果存在就會執行Scope#get方法

  1. Scope scope = this.scopes.get(scopeName); 
  2. Object scopedInstance = scope.get(beanName, () -> { 
  3.   beforePrototypeCreation(beanName); 
  4.   try { 
  5.     return createBean(beanName, mbd, args); 
  6.   } finally { 
  7.     afterPrototypeCreation(beanName); 
  8.   } 
  9. }); 

2 自定義Scope

自定義Scope

  1. public class CustomScope implements Scope { 
  2.      
  3.   private Object target ; 
  4.  
  5.   @Override 
  6.   public Object get(String name, ObjectFactory<?> objectFactory) { 
  7.     return target != null ? target : objectFactory.getObject() ; 
  8.   } 
  9.   // 如果調用了這個方法,那么下次在注入有@Scope("custom")的bean時 將會重寫調用objectFactory.getObject()方法。 
  10.   @Override 
  11.   public Object remove(String name) { 
  12.     target = null ; 
  13.     return "success" ; 
  14.   } 
  15.  
  16.   @Override 
  17.   public void registerDestructionCallback(String name, Runnable callback) { 
  18.   } 
  19.  
  20.   @Override 
  21.   public Object resolveContextualObject(String key) { 
  22.     return null
  23.   } 
  24.  
  25.   @Override 
  26.   public String getConversationId() { 
  27.     return null
  28.   } 
  29.  

注冊Scope

  1. @Component 
  2. public class CustomScopeRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { 
  3.   @Override 
  4.   public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 
  5.     beanFactory.registerScope("custom", new CustomScope()) ; 
  6.   } 
  7.   @Override 
  8.   public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { 
  9.   } 

使用Scope

  1. @Component 
  2. @Scope("custom"
  3. public class ApplyScopeBean { 

示例

  1. @RestController 
  2. @RequestMapping("/refresh"
  3. @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) 
  4. public class RefreshController implements ApplicationContextAware{ 
  5.   @Resource 
  6.   private ApplyScopeBean scopeBean ; 
  7.   @Resource 
  8.   private CustomScope customScope ; 
  9.   @GetMapping("/custom"
  10.   public String custom() { 
  11.     return scopeBean.getCustom() ; 
  12.   } 
  13.   @GetMapping("/remove")  
  14.   public Object remove() { 
  15.     return customScope.remove("applyScopeBean") ; 
  16.   }   

這里將Controller設置為多例,以便查看效果。交替執行上面的接口,只要刪除了就會創建新的實例。

3 多例注入

如果一個Bean 設置了@Scope(value =

ConfigurableBeanFactory.SCOPE_PROTOTYPE) 當這個Bean需要在一個單例Bean中被注入時,需要如下配置才可

  1. @Component 
  2. @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS) 
  3. public class ApplyScopeBean { 

這樣才能正確地注入Bean,否則因為本身使用者是單例的,屬性只會被初始化一次。也可以在每次使用前調用BeanFactory#getBean()。

 

責任編輯:姜華 來源: 今日頭條
相關推薦

2023-09-05 08:23:56

SpringScope方法

2024-01-05 08:38:20

SpringBeanScope

2011-03-18 09:27:00

Spring

2020-11-19 07:49:24

JS變量作用域

2023-09-27 08:33:16

作用域CSS

2022-11-29 17:38:57

DockerfileARG作用域

2023-06-29 08:32:41

Bean作用域

2011-09-06 09:56:24

JavaScript

2019-03-13 08:00:00

JavaScript作用域前端

2021-03-09 08:35:51

JSS作用域前端

2010-08-27 09:51:41

DHCP服務器

2021-12-06 07:15:48

Javascript作用域閉包

2010-09-25 16:10:09

添加DHCP作用域

2010-09-29 15:02:23

DHCP作用域

2021-03-17 08:39:24

作用域作用域鏈JavaScript

2016-09-19 13:52:26

Javascript跨域前端

2021-03-16 22:25:06

作用域鏈作用域JavaScript

2024-11-26 17:43:51

2024-11-14 14:53:04

2021-03-09 08:50:58

JavaScript前端作用域
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产欧美精品一区二区色综合朱莉 | 亚洲国产aⅴ成人精品无吗 亚洲精品久久久一区二区三区 | 一区二区三区在线免费看 | 国产一区二区三区四区三区四 | 国产成人jvid在线播放 | 成人黄色a | 久久成人免费 | 国产精品毛片 | 四虎影院在线观看免费视频 | 国产精品久久777777 | 天天躁日日躁性色aⅴ电影 免费在线观看成年人视频 国产欧美精品 | 国产成人艳妇aa视频在线 | 中文字幕 在线观看 | 国产精品久久久久久久久久久久久久 | 一区二区免费在线观看 | 国产午夜精品一区二区三区在线观看 | 国产精品国产成人国产三级 | 亚洲一区久久久 | 黄色国产 | 亚洲精品一区二区 | 久久综合888 | 最近免费日本视频在线 | 天天操天天干天天爽 | 免费视频一区 | www.操.com| 色综合久久久 | 欧洲毛片 | 五月婷婷丁香 | 天天干人人 | 最新午夜综合福利视频 | 91精品一区 | 欧美久久久久久 | a级在线 | 久久综合一区二区 | 国产在线高清 | 色呦呦网站 | 91免费观看在线 | 一区二区三区高清不卡 | 国产视频精品在线观看 | 嫩草懂你的影院入口 | 视频一区二区中文字幕日韩 |