在 T 中为 T 的所有可能值注册一次泛型 bean

问题描述 投票:0回答:1

我正在寻找一种在 T 中注册一次泛型类 bean 的方法,以便它可以在 IoC 容器中用于 T 的所有可能值。

示例如下(我使用的是 java 17 和 org.springframework:spring-beans:6.0.11)

@Getter
@RequiredArgsConstructor 
public class Item<T> {
    private final T value;
}

@Component
public class A {}

@Component
public class B {}

@Configuration
@ComponentScan("my.package")
public class Config {
   //the following method doesn't work
   //I'm putting it here just to explain what I'm trying to achieve
   @Bean
   public <T> Item<T> item(T value) {
      return new Item<>(value);
   }
}

@SpringBootTest
@ContextConfiguration(Config.class)
class MyTest {
   @Autowired
   Item<A> itemA;

   @Autowired
   Item<B> itemB;

   @Test
   void myTest() {
      //the test fails when loading the spring context because itemA and itemB cannot be resolved
      assert itemA != null;
      assert itemB != null;

   }
   
}

我知道理论上我想要做的事情是无法实现的,因为类型擦除,但是 spring 怎么可能为 jakarta.inject.Provider 实现类似的行为呢?

以下作品:

@Component
public class A {}

@Component
public class B {}

@Configuration
@ComponentScan("my.package")
public class Config {
}

@SpringBootTest
@ContextConfiguration(Config.class)
class MyTest {
   @Autowired
   Provider<A> providerA;

   @Autowired
   Provider<B> providerB;

   @Test
   void myTest() {
      assert providerA != null;
      assert providerB != null;

   }

}
java spring generics dependency-injection
1个回答
0
投票

就像List strings=new ArrayList();尽管被实例化为原始类型(不带泛型),但仍将正确返回字符串,以同样的方式,可以自动装配不带泛型类型的 Provider (

new Provider()
),并且一旦将其分配给 Provider,它将正确返回类型 B。然而,这与您的用例不同,您希望在 @Bean 定义中获取 T 值,但仍然没有说明它应该是哪个值。区别在于一个必须在编译时知道(T 值),而另一个(Provider 的类型)可以留到运行时)

您可以实现类似的功能,但您必须在某处定义

T value
,以便它可以自动连接到
item
Bean,或者稍微更改您的 bean 定义 - 例如以下内容将起作用:

public class Item<T> {
    private T data;

    public T get() {
        return data;
    }
}
// generics here don't play a role, could have also left them out
@Bean
public <T> Item<T> item() { 
    // you should still add some logic on how to set `data` based on whatever condition
    return new Item<>();
}

然后将其自动装配为特定类型:

@Autowired
Item<String> item; //will correcly get autowired and return the type String
© www.soinside.com 2019 - 2024. All rights reserved.