簡體   English   中英

春季注入的豆在嵌套類中為空

[英]Spring injected beans null in nested class

我有一個帶有2個靜態嵌套類的類,它們對2種不同的泛型類型執行相同的操作。

我像平時一樣將這兩個類公開為bean,並為構造函數添加了@Autowired。

這是基本設置

abstract class <T> Parent implements MyInterface<T> {
   private final Service service;
   Parent(Service service){ this.service = service; }

   @Override public final void doInterfaceThing(T thing){
     T correctedT = map(thing);
     service.doTheThing(correctedT);
   }

   protected abstract T map(T t);

   @Service
   public static class ImplA extends Parent<A> {
     @Autowired ImplA (Service service){ super(service); }
     A map(A a){ //map a }
   }

   @Service
   public static class ImplB extends Parent<B> {
     @Autowired ImplB (Service service){ super(service); }
     B map(B b){ //map b }
   }

}

在另一堂課上

@Service
public class Doer {
   private final List<MyInterface<A>> aImpls;
   @Autowired public Doer(List<MyInterface<A>> aImpls){ this.aImpls = aImpls; }
   public void doImportantThingWithA(A a){
     aImpls.get(0).doInterfaceThing(a);
   }
}

當我運行該應用程序時,所有內容似乎都已正確注入,並且當我在ImplA和ImplB構造函數中添加斷點時,“服務”的值不為null。 我在Doer的aImpls列表中也有一個ImplA bean。

但是,當我調用doImportantThingWithA(a)時,ImplA中的“服務”為空,因此我顯然死了。

我不確定這怎么可能,因為:

  1. 我在服務的構造函數中看到一個非空值,這是一個最終字段。
  2. 如果spring將ImplA和ImplB注入另一個類,則它應該已經將Service注入了ImplA或ImplB,或者在bean初始化時引發了異常。 我沒有設置延遲加載的任何內容,並且需要所有bean依賴項。

嵌套類的原因是因為這兩個實現之間唯一發生變化的是map()函數。 嘗試避免1行變化代碼的額外類。

更多信息:當我在Parent.doInterfaceThing()中添加斷點時,如果在“服務”上添加監視,則該值將為null。 如果我添加一個getService()方法,然后調用getService()而不是直接引用this.service,我將獲得正確的服務bean。 我不知道這意味着什么,但是代理似乎有些奇怪。

看起來是引起問題的原因是Parent.doInterfaceThing();。

如果我從方法簽名中刪除final,則正確填充“服務”字段,並且代碼按預期工作。

我根本不理解為什么更改方法簽名會影響類中final字段的注入值...但現在可以使用。

我對“使用映射器”評論的意思是這樣的:

class MyInterfaceImpl implements MyInterface {
   @Autowired
   private final Service service;

   @Override public final <T> void doInterfaceThing(T thing, UnaryOperator<T> mapper){
     T correctedT = mapper.apply(thing);
     service.doTheThing(correctedT);
   }

   // new interface to allow autowiring despite type erasure
   public interface MapperA extends UnaryOperator<A> {
     public A map(A toMap);
     default A apply(A a){ map(a); }
   }
   @Component
   static class AMapper implements MapperA {
       public A map(A a) { // ... }
   }

   public interface MapperB extends UnaryOperator<B> {
     public B map(B toMap);
     default B apply(B b){ map(b); }
   }
   @Component
   static class BMapper implements MapperB {
       public B map(B a) { // ... }
   }
}

這確實比原始行多了幾行,但並不多。 但是,您確實有更好的關注點分離。 我確實想知道自動裝配如何在具有泛型的代碼中工作,它看起來確實會引起問題。

您的客戶看起來像這樣:

@Service
public class Doer {
   private final List<MapperA> aMappers;
   private final MyInterface myInterface;
   @Autowired public Doer(MyInterface if, List<MapperA> mappers){ 
       this.myInterface = if;
       this.aImpls = mappers; }
   public void doImportantThingWithA(A a){
     aMappers.stream().map(m -> m.map(a)).forEach(myInterface::doInterfaceThing);
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM