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

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

開發 前端
如果當前你配置的@Scope不是singleton及prototype那么從scopes集合中取(這個集合是通過AbstractBeanFactory#registerScope方法進行注冊的,一般我們可以通過BeanDefinitionRegistryPostProcessor進行注冊),如果集合中也不存在那么就會拋出異常。如果存在就會執行Scope#get方法。

1 Scope作用

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

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

protected <T> T doGetBean(
            String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
            throws BeansException {
  String beanName = transformedBeanName(name);
  Object bean;
  // Eagerly check singleton cache for manually registered singletons.
  Object sharedInstance = getSingleton(beanName);
  if (sharedInstance != null && args == null) {
    // other code
  } else {
    // other code
    try {
      RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
      checkMergedBeanDefinition(mbd, beanName, args);


      // Guarantee initialization of beans that the current bean depends on.
      // other code
      // Create bean instance.
      // 根據BeanDefinition中定義的Scope創建實例
      // 判斷如果是單例
      if (mbd.isSingleton()) {
        // 如果是單例Bean會將Bean保存到緩存中singletonObjects  
        sharedInstance = getSingleton(beanName, () -> {
          try {
            return createBean(beanName, mbd, args);
          } catch (BeansException ex) {
            destroySingleton(beanName);
            throw ex;
          }
        });
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
      }
      // 判斷如果是原型(多例)
      else if (mbd.isPrototype()) {
        // It's a prototype -> create a new instance.
        Object prototypeInstance = null;
        try {
          beforePrototypeCreation(beanName);
          prototypeInstance = createBean(beanName, mbd, args);
        } finally {
          afterPrototypeCreation(beanName);
        }
        bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
      } 
      else {
        String scopeName = mbd.getScope();
        if (!StringUtils.hasLength(scopeName)) {
          throw new IllegalStateException("No scope name defined for bean 麓" + beanName + "'");
        }
        Scope scope = this.scopes.get(scopeName);
        // 當集合中也不存在時拋出異常  
        if (scope == null) {
          throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
        }
        try {
          Object scopedInstance = scope.get(beanName, () -> {
            beforePrototypeCreation(beanName);
            try {
              return createBean(beanName, mbd, args);
            } finally {
              afterPrototypeCreation(beanName);
            }
          });
          bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
        } catch (IllegalStateException ex) {
          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);
        }
      }
    } catch (BeansException ex) {
      cleanupAfterBeanCreationFailure(beanName);
      throw ex;
    }
  }
  // other code
  return (T) bean;
}

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

Scope scope = this.scopes.get(scopeName);
Object scopedInstance = scope.get(beanName, () -> {
  beforePrototypeCreation(beanName);
  try {
    return createBean(beanName, mbd, args);
  } finally {
    afterPrototypeCreation(beanName);
  }
});

2 自定義Scope

自定義Scope

public class CustomScope implements Scope {
    
  private Object target ;


  @Override
  public Object get(String name, ObjectFactory<?> objectFactory) {
    return target != null ? target : objectFactory.getObject() ;
  }
  // 如果調用了這個方法,那么下次在注入有@Scope("custom")的bean時 將會重寫調用objectFactory.getObject()方法。
  @Override
  public Object remove(String name) {
    target = null ;
    return "success" ;
  }


  @Override
  public void registerDestructionCallback(String name, Runnable callback) {
  }


  @Override
  public Object resolveContextualObject(String key) {
    return null;
  }


  @Override
  public String getConversationId() {
    return null;
  }


}

注冊Scope

@Component
public class CustomScopeRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    beanFactory.registerScope("custom", new CustomScope()) ;
  }
  @Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
  }
}

使用Scope

@Component
@Scope("custom")
public class ApplyScopeBean {
}

示例

@RestController
@RequestMapping("/refresh")
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class RefreshController implements ApplicationContextAware{
  @Resource
  private ApplyScopeBean scopeBean ;
  @Resource
  private CustomScope customScope ;
  @GetMapping("/custom")
  public String custom() {
    return scopeBean.getCustom() ;
  }
  @GetMapping("/remove") 
  public Object remove() {
    return customScope.remove("applyScopeBean") ;
  }  
}

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

3 多例注入

如果一個Bean 設置了@Scope(value =ConfigurableBeanFactory.SCOPE_PROTOTYPE) 當這個Bean需要在一個單例Bean中被注入時,需要如下配置才可

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

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

責任編輯:武曉燕 來源: Spring全家桶實戰案例源碼
相關推薦

2021-07-05 08:43:46

Spring Beanscope作用域

2011-03-18 09:27:00

Spring

2024-01-05 08:38:20

SpringBeanScope

2020-11-19 07:49:24

JS變量作用域

2022-11-29 17:38:57

DockerfileARG作用域

2023-09-27 08:33:16

作用域CSS

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-06-02 07:02:42

js作用域函數

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

2016-09-19 13:52:26

Javascript跨域前端

2024-11-26 17:43:51

2024-11-14 14:53:04

2021-03-16 22:25:06

作用域鏈作用域JavaScript
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 黄网免费看 | 神马久久香蕉 | 一区| 亚洲精品1区 | 久久久久国产一区二区三区四区 | www.操.com| 日韩成人在线视频 | 色久影院 | 国产一区二区影院 | 亚洲成网站| 欧美日本在线 | 国产精品一区二区福利视频 | 在线中文字幕日韩 | 日韩精品久久久久久 | 国产精品欧美一区二区三区不卡 | 久久一级 | 91久久精品国产 | 日韩电影免费在线观看中文字幕 | 成人国产精品入口免费视频 | 国产精品久久久久久久久久久久久久 | 中文字幕av免费 | 精精国产xxxx视频在线播放 | 久国产视频 | 成人国产精品久久 | 区一区二区三在线观看 | 欧美在线观看一区二区 | 成人av网站在线观看 | 欧美一级免费看 | 欧美色a v | 91免费在线| 中文字幕视频在线看 | 成人午夜免费福利视频 | 福利片一区二区 | 激情欧美日韩一区二区 | 亚洲视频区 | 亚洲一区二区三区免费 | 国产香蕉视频在线播放 | 午夜电影网址 | 少妇一级淫片免费播放 | 国产美女一区 | 欧美精品一区二区三区在线 |