亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

彈簧注入通用類型

彈簧注入通用類型

牧羊人nacy 2023-02-23 15:57:46
假設我們有這樣一個界面:public interface Validator<T> {  boolean isValid(T data);}這是核心模塊的一部分。多個應用程序可以使用相同的核心模塊,通用 T 具有不同的值。一個示例實現是(來自應用程序的特定模塊):@Componentpublic class AppValidator implements Validator<String> {  @Override  public boolean isValid(String data) {    return false;  }}然后在控制器中(它是核心模塊的一部分):@RestControllerpublic class ValidateController {  @Autowired  private Validator validator;  @RequestMapping("/")  public void index() {    validator.validate("");  }}IntelliJ 抱怨我使用的是原始類型;如您所見,我實際上是在控制器中這樣做的。我的問題:有沒有辦法以有界的方式注入依賴項(而不是注入Validator,注入Validator<String>)?但當然,綁定類型可能會根據使用核心模塊的應用程序而改變?如果不可能(可能是由于類型擦除),最好的做法是什么?只是為了使用嗎Object?有沒有更好的替代方案仍然提供類型安全?我在某個地方看到有人說可以在編譯時做一些魔術來改變類型,但我不確定如何,或者即使我讀對了?我正在使用 Spring,所以我希望 Spring 可以在這里提供一些幫助!歡迎施展魔法
查看完整描述

2 回答

?
一只名叫tom的貓

TA貢獻1906條經驗 獲得超3個贊

答案很簡單:您不需要任何魔法,它只在 Spring 中起作用。你有你的AppValidator,然后你就做(它是通過查看泛型類型注入的):


@Autowired 

private Validator<String> appValidator;

好吧,現在假設你有兩個Validator<String>,然后呢?required a single bean but found two exception- 就是這樣。這就是為什么這是一種可怕的做法,永遠不要這樣做。


在我的工作中,一個人創建了具有 3 個泛型類型的泛型接口,然后基于這些泛型類型進行注入,人們仍然討厭他。它看起來像這樣,是的,只要您在多個實現中沒有以完全相同的順序使用完全相同的 3 個泛型類型,它就可以工作:


@Autowired

private Invoker<String, Integer, Person> personInvoker;


@Autowired

private Invoker<Integer, String, Animal> animalInvoker;

即使您的代碼中沒有多個Validator<String>,并且您不打算擁有更多 - 其他人可能會進來并添加它們,或者在許多其他情況下。


查看完整回答
反對 回復 2023-02-23
?
慕哥9229398

TA貢獻1877條經驗 獲得超6個贊

這里是您的模塊(應用程序和核心)之間的關系:


Application 1       Application 2      Application 3

     |                   |                   |

Validator<Foo>     Validator<Bar>     Validator<FooBar>

     |                   |                   |  

     |                   |                   |  

     |__ __ __ __ __ __ _| __ __ __ __ __ __ | 

                         |

                         | <<uses>>

                         |

                        \ /

                     Core Module    

                         |

                 ValidateController  (not generic rest controller)                   

這里有些不對勁,因為您希望共享組件ValidateController依賴于特定的應用程序泛型Validator類而 ValidateController不是泛型類,因此您只能堅持使用Object該Validator字段的泛型類型。

為了使事情保持一致,您應該創建這個缺失的鏈接。事實上,您需要不同的控制器子類,因為每個控制器都需要使用特定的驗證器實例。

例如,您可以ValidateController在共享/代碼模塊中定義一個抽象類/接口,并讓每個子類擴展它并為自己定義Validator要使用的通用類。


這里是你的模塊之間的目標關系:


Application 1        Application 2        Application 3

     |                   |                      |

Validator<Foo>       Validator<Bar>       Validator<FooBar>

FooController(bean)  BarController(bean)  FooBarController(bean)

     |                   |                      |  

     |                   |                      |  

     |__ __ __ __ __ ___ | __ ___ __ __ __ __ __| 

                         |

                         | <<uses>>

                         |

                        \ /

                     Core Module    

                         |

                 ValidateController<T>  (abstract class and not a bean)                   

例如在核心/共享模塊中:


public abstract class ValidateController<T> {


  private Validator<T> validator;


  ValidateController(Validator<T> validator){

     this.validator = validator;

  }


  @RequestMapping("/")

  public void index(T t) {

    boolean isValid = validator.validate(t);

  }


}

在應用程序中,定義您的驗證器實現:


@Component

public class AppValidator implements Validator<String> {

  @Override

  public boolean validate(String data) {

    return ...;

  }

}

并定義StringController子類(或@Bean作為替代)以設置正確的Validator:


@RestController

public class StringController extends ValidateController<String>{


   public ValidateControllerApp(Validator<String> validator){

       this.validator = validator;

   }


}


查看完整回答
反對 回復 2023-02-23
  • 2 回答
  • 0 關注
  • 133 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號