最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

說說Spring中為何要引入Lookup注解

 更新時(shí)間:2021年01月15日 14:37:30   作者:johnwonder  
這篇文章主要給大家介紹了關(guān)于Spring中為何要引入Lookup注解的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

我們先探一探官方文檔關(guān)于Method Injection的章節(jié)是怎么說的:

In most application scenarios, most beans in the container are singletons. When a singleton bean needs to collaborate with another singleton bean or a non-singleton bean needs to collaborate with another non-singleton bean, you typically handle the dependency by defining one bean as a property of the other. A problem arises when the bean lifecycles are different. Suppose singleton bean A needs to use non-singleton (prototype) bean B, perhaps on each method invocation on A. The container creates the singleton bean A only once, and thus only gets one opportunity to set the properties. The container cannot provide bean A with a new instance of bean B every time one is needed.

用一句話概括就是 一個(gè)單例Bean A每次獲取另外一個(gè)Bean B的時(shí)候怎么保證這個(gè)Bean B是一個(gè)新的實(shí)例?

正文

ApplicationContextAware接口

官方文檔首先也提到了一個(gè)解決方案就是把A弄成容器的Aware( make bean A aware of the container),也就是實(shí)現(xiàn)ApplicationContextAware接口。

A solution is to forego some inversion of control. You can make bean A aware of the container by implementing the ApplicationContextAware interface, and by making a getBean("B") call to the container ask for (a typically new) bean B instance every time bean A needs it. The following example shows this approach

文檔里隨后就提供了一個(gè)示例來說明這個(gè)解決方案如何做。

// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;
// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class CommandManager implements ApplicationContextAware {
 private ApplicationContext applicationContext;
 public Object process(Map commandState) {
  // grab a new instance of the appropriate Command
  Command command = createCommand();
  // set the state on the (hopefully brand new) Command instance
  command.setState(commandState);
  return command.execute();
 }
 protected Command createCommand() {
  // notice the Spring API dependency!
  return this.applicationContext.getBean("command", Command.class);
 }
  public void setApplicationContext(
   ApplicationContext applicationContext) throws BeansException {
  this.applicationContext = applicationContext;
 }
 }

雖然解決了一開始提出的問題,但是Spring隨后就說到:

The preceding is not desirable, because the business code is aware of and coupled to the Spring Framework. Method Injection, a somewhat advanced feature of the Spring IoC container, lets you handle this use case cleanly.

也就是說 前面的方法是不可取的,因?yàn)闃I(yè)務(wù)代碼知道并耦合到Spring框架。那怎么降低這個(gè)耦合度呢?后半句就給出了答案:方法注入是Spring IOC容器的一個(gè)稍微高級(jí)的特性,它允許您干凈地處理這個(gè)用例。

Lookup Method方法注入

首先再次引入官方文檔中的闡述:

Lookup method injection is the ability of the container to override methods on container-managed beans and return the lookup result for another named bean in the container. The lookup typically involves a prototype bean, as in the scenario described in the preceding section. The Spring Framework implements this method injection by using bytecode generation from the CGLIB library to dynamically generate a subclass that overrides the method.

簡要概括下這段話有三個(gè)意思:

  • Lookup Method注入可以讓容器重寫容器中bean上的方法并返回容器中另一個(gè)bean的查找結(jié)果。
  • Lookup通常會(huì)是一個(gè)原型bean,如文章開頭所說的。
  • Spring框架通過使用CGLIB庫中的字節(jié)碼生成來動(dòng)態(tài)生成覆蓋該方法的子類,從而實(shí)現(xiàn)這種方法注入。

使用Lookup方式需要注意以下幾點(diǎn):

  • For this dynamic subclassing to work, the class that the Spring bean container subclasses cannot be final, and the method to be overridden cannot be final, either.
  • Unit-testing a class that has an abstract method requires you to subclass the class yourself and to supply a stub implementation of the abstract method.
  • Concrete methods are also necessary for component scanning, which requires concrete classes to pick up.
  • A further key limitation is that lookup methods do not work with factory methods and in particular not with @Bean methods in configuration classes, since, in that case, the container is not in charge of creating the instance and therefore cannot create a runtime-generated subclass on the fly.

這段話也可以概括為以下幾點(diǎn):

  1. 使這個(gè)動(dòng)態(tài)子類可以用,這個(gè)類不能是final,要重寫的方法也不能是final。
  2. 單元測試具有抽象方法的類需要您自己對(duì)該類進(jìn)行子類化,并提供抽象方法的存根實(shí)現(xiàn)。
  3. 具體的方法對(duì)于組件掃描也是必要的,這需要具體的類來獲取。
  4. 一個(gè)關(guān)鍵限制是Lookup方法不適用于工廠方法,尤其是配置類中的@Bean方法,因?yàn)樵谶@種情況下,容器不負(fù)責(zé)創(chuàng)建實(shí)例,因此不能動(dòng)態(tài)創(chuàng)建運(yùn)行時(shí)生成的子類。

接下來Spring就拿上面本來基于ApplicationContextAware的方法來說,就可以用Lookup來替換了。對(duì)于前面代碼段中的CommandManager類,Spring容器動(dòng)態(tài)重寫createCommand()方法的實(shí)現(xiàn)。CommandManager類沒有任何Spring依賴項(xiàng),如修改后的示例所示

In the case of the CommandManager class in the previous code snippet, the Spring container dynamically overrides the implementation of the createCommand() method. The CommandManager class does not have any Spring dependencies, as the reworked example shows.

Xml配置lookup-method

 public abstract class CommandManager { 
  public Object process(Object commandState) {
   // grab a new instance of the appropriate Command interface
   Command command = createCommand();
   // set the state on the (hopefully brand new) Command instance
   command.setState(commandState);
   return command.execute();

 }
 // okay... but where is the implementation of this method?
  protected abstract Command createCommand();
 }

在包含要注入的方法的CommandManager類中,要注入的方法需要以下形式的簽名:

<public|protected> [abstract] <return-type> theMethodName(no-arguments);

如果方法是抽象的,則動(dòng)態(tài)生成的子類將實(shí)現(xiàn)該方法。否則,動(dòng)態(tài)生成的子類將重寫在原始類中定義的具體方法。

我們來看下Bean的配置:

當(dāng)需要myCommand這個(gè)Bean的新實(shí)例時(shí),被標(biāo)識(shí)為commandManager的bean就會(huì)調(diào)用自己的createCommand()方法。如果需要的話,必須小心地將myCommand 這個(gè)bean部署為原型。如果是單例,則每次都返回相同的myCommand bean實(shí)例.

@Lookup注解

在基于注解的組件模型中,可以通過@lookup注釋聲明查找方法,如下例所示

 public abstract class CommandManager {
  public Object process(Object commandState) {
   Command command = createCommand();
   command.setState(commandState);
   return command.execute();
  }
  @Lookup("myCommand")
  protected abstract Command createCommand();
 }

或者,你也可以依靠目標(biāo)bean根據(jù)lookup方法的聲明返回類型進(jìn)行解析

public abstract class CommandManager {
  public Object process(Object commandState) {
   MyCommand command = createCommand();
   command.setState(commandState);
   return command.execute();
  }
  @Lookup
  protected abstract MyCommand createCommand();
 }

需要注意的是你通常應(yīng)該用一個(gè)具體的存根實(shí)現(xiàn)聲明這種帶注解的查找方法,以便它們與Spring的組件掃描規(guī)則兼容,默認(rèn)情況下抽象類會(huì)被忽略。此限制不適用于顯式注冊(cè)或顯式導(dǎo)入的bean類。也就是說如果用組件掃描Bean的話因?yàn)槌橄箢惸J(rèn)是被忽略的,但是你加上這個(gè)Lookup注解后就不會(huì)唄忽略。

Spring在最后也提供了其他兩種解決思路:

Another way of accessing differently scoped target beans is an ObjectFactory/ Provider injection point. See Scoped Beans as Dependencies。You may also find the ServiceLocatorFactoryBean (in the org.springframework.beans.factory.config package) to be useful.

  1. 通過ObjectFactory或者ObjectProvider.
  2. 通過ServiceLocatorFactoryBean.

這兩個(gè)方案我們之后會(huì)單獨(dú)寫文章來探討,下篇文章我打算來具體的使用下這個(gè)Lookup 方法注入并且從源碼角度來看下Spring如何巧妙地實(shí)現(xiàn)它的。

總結(jié)

到此這篇關(guān)于Spring中為何要引入Lookup注解的文章就介紹到這了,更多相關(guān)Spring為何引入Lookup內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解讀Hibernate、MyBatis有哪些區(qū)別

    解讀Hibernate、MyBatis有哪些區(qū)別

    Hibernate和MyBatis是Java中常用的持久層框架,各有優(yōu)勢(shì)和適用場景,Hibernate通過對(duì)象關(guān)系映射簡化數(shù)據(jù)庫操作,適合復(fù)雜業(yè)務(wù)邏輯;MyBatis提供更高的SQL控制權(quán),適合需要直接操作SQL的場景,選擇應(yīng)基于項(xiàng)目需求和團(tuán)隊(duì)習(xí)慣
    2025-01-01
  • Flink結(jié)合Kafka實(shí)現(xiàn)通用流式數(shù)據(jù)處理

    Flink結(jié)合Kafka實(shí)現(xiàn)通用流式數(shù)據(jù)處理

    這篇文章將和大家一起深入探討Flink和Kafka的關(guān)系以及它們?cè)跀?shù)據(jù)流處理中的應(yīng)用,并提供一些最佳實(shí)踐和實(shí)際案例,希望對(duì)大家有一定的幫助
    2025-03-03
  • 淺談String類型如何轉(zhuǎn)換為time類型存進(jìn)數(shù)據(jù)庫

    淺談String類型如何轉(zhuǎn)換為time類型存進(jìn)數(shù)據(jù)庫

    這篇文章主要介紹了String類型如何轉(zhuǎn)換為time類型存進(jìn)數(shù)據(jù)庫,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java日期時(shí)間類(Date、DateFormat、Calendar)解析

    Java日期時(shí)間類(Date、DateFormat、Calendar)解析

    這篇文章主要介紹了Java日期時(shí)間類(Date、DateFormat、Calendar)解析,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-06-06
  • Spring?Security自定義認(rèn)證邏輯實(shí)例詳解

    Spring?Security自定義認(rèn)證邏輯實(shí)例詳解

    這篇文章主要給大家介紹了關(guān)于Spring?Security自定義認(rèn)證邏輯的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-01-01
  • SpringBoot 下在 yml 中的 logging 日志配置方法

    SpringBoot 下在 yml 中的 logging 日志配置方法

    logging 配置主要用于控制應(yīng)用程序的日志輸出行為,可以通過配置定制日志的格式、級(jí)別、輸出位置等,這篇文章主要介紹了SpringBoot 下在 yml 中的 logging 日志配置,需要的朋友可以參考下
    2024-06-06
  • Java多線程中sleep和wait區(qū)別

    Java多線程中sleep和wait區(qū)別

    本文主要介紹了Java多線程中sleep和wait區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Java并發(fā)編程之CountDownLatch的使用

    Java并發(fā)編程之CountDownLatch的使用

    CountDownLatch是一個(gè)倒數(shù)的同步器,常用來讓一個(gè)線程等待其他N個(gè)線程執(zhí)行完成再繼續(xù)向下執(zhí)行,本文主要介紹了CountDownLatch的具體使用方法,感興趣的可以了解一下
    2023-05-05
  • Java中的HashMap和Hashtable區(qū)別解析

    Java中的HashMap和Hashtable區(qū)別解析

    這篇文章主要介紹了Java中的HashMap和Hashtable區(qū)別解析,HashMap和Hashtable都實(shí)現(xiàn)了Map接口,但決定用哪一個(gè)之前先要弄清楚它們之間的區(qū)別,主要的區(qū)別有線程安全性、同步和速度,需要的朋友可以參考下
    2023-11-11
  • Springboot整合Mybatispuls的實(shí)例詳解

    Springboot整合Mybatispuls的實(shí)例詳解

    這篇文章主要介紹了Springboot整合Mybatispuls的相關(guān)資料,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11

最新評(píng)論

兴安盟| 新泰市| 凌云县| 苏尼特左旗| 广河县| 青田县| 奉贤区| 潼南县| 福州市| 平顶山市| 临沂市| 湟源县| 信宜市| 绍兴县| 栾城县| 璧山县| 阿荣旗| 冀州市| 罗田县| 平陆县| 鄂尔多斯市| 成安县| 广州市| 革吉县| 河西区| 吉林省| 陇川县| 乐山市| 明星| 衡阳市| 高陵县| 呼伦贝尔市| 柳河县| 桓仁| 南城县| 遂平县| 张家川| 崇礼县| 黔西| 嘉祥县| 荔波县|