如何使用泛型类型的 Bean 进行配置类?(包括示例)



我想提供一个基本配置类,该类将处理创建具有泛型类型的 bean,该泛型类型在您扩展类时定义,如下所示。但它从不调用@Bean方法。

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.client.RestTemplate;
import java.lang.reflect.Constructor;
@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( classes = { TestGenericBean.MyClientCreator.class } )
public class TestGenericBean
{
    /* This throws an error saying no bean provided */
    @Autowired
    private TestClient client;
    public static class ClientConfig<T>
    {
        private Class<T> classCreator;
        public ClientConfig(Class<T> classCreator)
        {
            this.classCreator = classCreator;
        }
        /* This is never called */
        @Bean
        public T createClient(RestTemplate restTemplate) throws Exception
        {
            Constructor<T> constructor = classCreator.getConstructor(
                RestTemplate.class
            );
            return constructor.newInstance( restTemplate );
        }
        /* This is never called */
        @Bean
        public RestTemplate restTemplate()
        {
            return new RestTemplate();
        }
    }
    @Configuration
    public static class MyClientCreator extends ClientConfig<TestClient>
    {
        public MyClientCreator()
        {
            super( TestClient.class );
        }
    }
    public static class TestClient
    {
        public RestTemplate restTemplate;
        public TestClient(RestTemplate restTemplate)
        {
            this.restTemplate = restTemplate;
        }
    }
    @Test
    public void testBean()
    {
        System.out.print( client.restTemplate );
    }
}

不知道为什么,但它需要一个 MappingJackson2HttpMessageConverter 类型的 bean。有了这个,它就可以工作了。

@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( classes = { TestGenericBean.MyClientCreator.class } )
public class TestGenericBean
{
    @Autowired
    private TestClient client;
    public static class ClientConfig<T>
    {
        private Class<T> classCreator;
        public ClientConfig(Class<T> classCreator)
        {
            this.classCreator = classCreator;
        }
        /**** THIS IS REQUIRED - WHY? ****/
        @Bean
        public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter()
        {
            return new MappingJackson2HttpMessageConverter();
        }
        @Bean
        public T createClient(AsyncRestTemplate asyncRestTemplate) throws Exception
        {
            Constructor<T> constructor = classCreator.getConstructor(
                AsyncRestTemplate.class
            );
            return constructor.newInstance( asyncRestTemplate );
        }
        @Bean
        public AsyncRestTemplate asyncRestTemplate()
        {
            return new AsyncRestTemplate();
        }
    }
    @Configuration
    public static class MyClientCreator extends ClientConfig<TestClient>
    {
        public MyClientCreator()
        {
            super( TestClient.class );
        }
    }
    public static class TestClient
    {
        public AsyncRestTemplate asyncRestTemplate;
        public TestClient(AsyncRestTemplate asyncRestTemplate)
        {
            this.asyncRestTemplate = asyncRestTemplate;
        }
    }
    @Test
    public void testBean()
    {
        System.out.print( client.asyncRestTemplate );
    }
}

我最近没有经常使用 Spring/Spring boot,但我在注释预处理器方面有很多经验。Spring boot 使用它们的方式不允许将任何泛型方法用作@autowire的 Bean 提供程序。这是因为它无法安全地解析 Java 类,因此无法将其与字段映射。我建议您尝试使用包装类,例如 Getter 或 List,但不能保证任何泛型实现都可以工作。

相关内容

  • 没有找到相关文章

最新更新