自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

開(kāi)發(fā) 前端
通過(guò)@Scope注解可以指定Bean的作用域,默認(rèn)情況都是單例的(ConfigurableBeanFactory.SCOPE_SINGLETON=singleton),在創(chuàng)建bean實(shí)例時(shí)就是根據(jù)當(dāng)前定義BeanDefinition中的Scope來(lái)做不同的創(chuàng)建。

[[409240]]

環(huán)境:spring5.3.3

1 Scope作用

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

在創(chuàng)建bean實(shí)例時(shí)就是根據(jù)當(dāng)前定義BeanDefinition中的Scope來(lái)做不同的創(chuàng)建,源碼如下:

  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.       // 根據(jù)BeanDefinition中定義的Scope創(chuàng)建實(shí)例 
  20.       // 判斷如果是單例 
  21.       if (mbd.isSingleton()) { 
  22.         // 如果是單例Bean會(huì)將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.         // 當(dāng)集合中也不存在時(shí)拋出異常   
  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,如果都不是則會(huì)從Map<String, Scope> scopes中獲取。如果當(dāng)前你配置的@Scope不是singleton及prototype那么從scopes集合中?。ㄟ@個(gè)集合是通過(guò)AbstractBeanFactory#registerScope方法進(jìn)行注冊(cè)的,一般我們可以通過(guò)
BeanDefinitionRegistryPostProcessor進(jìn)行注冊(cè)),如果集合中也不存在那么就會(huì)拋出異常。如果存在就會(huì)執(zhí)行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.   // 如果調(diào)用了這個(gè)方法,那么下次在注入有@Scope("custom")的bean時(shí) 將會(huì)重寫(xiě)調(diào)用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.  

注冊(cè)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設(shè)置為多例,以便查看效果。交替執(zhí)行上面的接口,只要?jiǎng)h除了就會(huì)創(chuàng)建新的實(shí)例。

3 多例注入

如果一個(gè)Bean 設(shè)置了@Scope(value =

ConfigurableBeanFactory.SCOPE_PROTOTYPE) 當(dāng)這個(gè)Bean需要在一個(gè)單例Bean中被注入時(shí),需要如下配置才可

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

這樣才能正確地注入Bean,否則因?yàn)楸旧硎褂谜呤菃卫?,屬性只?huì)被初始化一次。也可以在每次使用前調(diào)用BeanFactory#getBean()。

 

責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

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服務(wù)器

2021-12-06 07:15:48

Javascript作用域閉包

2010-09-29 15:02:23

DHCP作用域

2010-09-25 16:10:09

添加DHCP作用域

2021-03-17 08:39:24

作用域作用域鏈JavaScript

2021-03-16 22:25:06

作用域鏈作用域JavaScript

2016-09-19 13:52:26

Javascript跨域前端

2021-03-09 08:50:58

JavaScript前端作用域

2024-11-26 17:43:51

2010-08-25 15:19:20

DHCP作用域
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)