1

我有一个基本的自动配置类,它使用泛型来创建你想要的 bean。但是当我测试有两个都扩展该基本配置类的配置时,第二个永远不会创建它的 bean。

我相信这是因为两者的方法名称相同,所以 Spring 假定它已经创建。

有没有办法根据泛型类型动态设置名称?(或其他一些解决方案)

@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( classes = { TestGenericBean.MyClientCreator.class, TestGenericBean.MyClientCreator2.class } )
public class TestGenericBean
{
    @Autowired
    private TestClient client;

    @Autowired
    private TestClient2 client2;

    public static class ClientConfig<T>
    {
        private Class<T> classCreator;

        public ClientConfig(Class<T> classCreator)
        {
            this.classCreator = classCreator;
        }

        /* ***** This base class's method is only called once for
         *       the first class (MyClientCreator) not for the
         *       second one (MyClientCreator2)
         */
        @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;
        }
    }

    /* This is the second configuration class. This config's bean never gets created */
    @Configuration
    public static class MyClientCreator2 extends ClientConfig<TestClient2>
    {
        public MyClientCreator2()
        {
            super( TestClient2.class );
        }
    }

    public static class TestClient2
    {
        public AsyncRestTemplate asyncRestTemplate;

        public TestClient2(AsyncRestTemplate asyncRestTemplate)
        {
            this.asyncRestTemplate = asyncRestTemplate;
        }
    }

    @Test
    public void testBean()
    {
        System.out.print( client.asyncRestTemplate );
    }
}
4

1 回答 1

0

createClient您可以通过继承该方法、删除@Bean父类上的注释并限定 bean 标题中的名称来解决您的问题:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestGenericBean.MyClientCreator.class, TestGenericBean.MyClientCreator2.class })
public class TestGenericBean {

    // Need to remove the bean here so we don't get duplicate naming
    // @Bean
    public T createClient(AsyncRestTemplate asyncRestTemplate) throws Exception
    {
       ...
    }

    ...

    @Configuration
    public static class MyClientCreator extends ClientConfig<TestClient> {
        public MyClientCreator()
        {
            super( TestClient.class );
        }
        @Bean("testClient")
        @Override
        public TestClient createClient(AsyncRestTemplate asyncRestTemplate) throws Exception {
            return super.createClient(asyncRestTemplate);
        }
    }

    ...

    /*
     * This is the second configuration class. This config's bean never gets created
     */
    @Configuration
    public static class MyClientCreator2 extends ClientConfig<TestClient2> {
        public MyClientCreator2()
        {
            super( TestClient2.class );
        }
        @Bean("testClient2")
        @Override
        public TestClient2 createClient(AsyncRestTemplate asyncRestTemplate) throws Exception {
            return super.createClient(asyncRestTemplate);
        }
    }

    ...
}

但是,理想情况下,如果您可以控制 bean,则应该对非构造函数/DI 友好的 bean使用出色的Object Factory (和类似)方法。干杯!

于 2018-01-22T21:32:43.570 回答