溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring中引入Lookup注解的作用是什么

發(fā)布時間:2021-01-15 17:14:51 來源:億速云 閱讀:414 作者:Leah 欄目:開發(fā)技術

本篇文章為大家展示了Spring中引入Lookup注解的作用是什么,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

ApplicationContextAware接口

官方文檔首先也提到了一個解決方案就是把A弄成容器的Aware( make bean A aware of the container),也就是實現(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

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

// 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è)務代碼知道并耦合到Spring框架。那怎么降低這個耦合度呢?后半句就給出了答案:方法注入是Spring IOC容器的一個稍微高級的特性,它允許您干凈地處理這個用例。

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.

簡要概括下這段話有三個意思:

  • Lookup Method注入可以讓容器重寫容器中bean上的方法并返回容器中另一個bean的查找結果。

  • Lookup通常會是一個原型bean,如文章開頭所說的。

  • Spring框架通過使用CGLIB庫中的字節(jié)碼生成來動態(tài)生成覆蓋該方法的子類,從而實現(xiàn)這種方法注入。

使用Lookup方式需要注意以下幾點:

  • 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.

這段話也可以概括為以下幾點:

  1. 使這個動態(tài)子類可以用,這個類不能是final,要重寫的方法也不能是final。

  2. 單元測試具有抽象方法的類需要您自己對該類進行子類化,并提供抽象方法的存根實現(xiàn)。

  3. 具體的方法對于組件掃描也是必要的,這需要具體的類來獲取。

  4. 一個關鍵限制是Lookup方法不適用于工廠方法,尤其是配置類中的@Bean方法,因為在這種情況下,容器不負責創(chuàng)建實例,因此不能動態(tài)創(chuàng)建運行時生成的子類。

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

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);

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

我們來看下Bean的配置:

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

@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();
 }

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

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

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

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.

上述內(nèi)容就是Spring中引入Lookup注解的作用是什么,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI