成人免费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作用域

2019-03-13 08:00:00

JavaScript作用域前端

2021-03-09 08:35:51

JSS作用域前端

2010-08-27 09:51:41

DHCP服務器

2011-09-06 09:56:24

JavaScript

2016-09-19 13:52:26

Javascript跨域前端

2010-09-29 15:02:23

DHCP作用域

2021-12-06 07:15:48

Javascript作用域閉包

2010-09-25 16:10:09

添加DHCP作用域

2021-03-16 22:25:06

作用域鏈作用域JavaScript

2021-03-17 08:39:24

作用域作用域鏈JavaScript

2024-11-26 17:43:51

2024-11-14 14:53:04

2021-03-09 08:50:58

JavaScript前端作用域
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 99精品国自产在线 | 99精品99久久久久久宅男 | 久久三区 | 精品产国自在拍 | 日本精品免费在线观看 | 亚洲精视频 | 国产精品夜夜春夜夜爽久久电影 | 国产精品美女久久久久久免费 | 国产毛片视频 | 久久久国产精品入口麻豆 | 91欧美激情一区二区三区成人 | 欧美在线观看免费观看视频 | 请别相信他免费喜剧电影在线观看 | www.日韩| 欧美日韩视频在线播放 | 国产成人精品一区二区三区视频 | 浮生影院免费观看中文版 | 天天躁日日躁狠狠很躁 | 日日摸夜夜添夜夜添特色大片 | 亚洲午夜视频 | 免费一级片 | 国产一区二区三区免费 | 亚洲人的av | 国产女人与拘做视频免费 | 中文字幕日韩一区 | 天天舔天天 | 国产精品亚洲精品久久 | 日本一二区视频 | 一级无毛片 | 在线视频一区二区三区 | 一区二区在线 | 免费观看www | 国产黄色在线观看 | 午夜视频在线免费观看 | 欧美一二三四成人免费视频 | 看av在线 | 日韩一区二区视频 | 一级片免费观看 | 亚洲精品一区中文字幕乱码 | 国产免费色 | 亚洲国产精品一区二区三区 |