[英]How allow base auto configuration class? When I have two that extend it, only the first one gets called
I have a base auto configuration class that uses generics to create the bean you want. 我有一个基本的自动配置类,该类使用泛型来创建所需的bean。 But when I test having two configs that both extend that base config class, the second one never creates its beans.
但是,当我测试有两个都扩展该基本配置类的配置时,第二个配置永远不会创建其bean。
I believe this is because the method name is the same on both, so Spring assumes that it's already created. 我相信这是因为方法名称在两者上都相同,因此Spring假定它已经创建。
Is there a way to dynamically set the name based off the generic type? 有没有一种方法可以根据通用类型动态设置名称? (or some other solution)
(或其他解决方案)
@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 );
}
}
You can solve your problem by inheriting the createClient
method, removing the @Bean
annotation on your parent class and qualifying the name in the bean title: 您可以通过继承
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);
}
}
...
}
However, ideally if you have control of the beans, you should be using the awesome Object Factory (and similar) methods for non-constructor/DI-friendly beans. 但是,理想情况下,如果您可以控制Bean,则应该对非构造函数/ DI友好的Bean使用令人敬畏的Object Factory (和类似方法)。 Cheers!
干杯!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.