在Config文件中用@Bean注解装配bean的一个问题

2019-10-20  本文已影响0人  猫尾草

Spring中配置与使用bean的一些方法参见https://www.jianshu.com/p/f3eaa90fb51e
*******************正文分割线*******************


  我们通常会在@Configuration注解的的类中使用@Bean注解来生成让Spring管理的JavaBean,例如:

@Configuration
public class Test {
  @Bean
  public UsedBean createBean() {
    return new UsedBean();
  }
}

public class UsedBean {
  // 省略
}

这样在其他地方就可以导入使用。

@Autowired
private UsedBean usedBean;

现在因为特殊原因,需要在项目中引入两个设置不同的RestTemplate

@Configuration
public class HttpConfig {

    /**
     * 使用到的HttpClientUtil.createHttpClient()、httpRequestFactory详见文末代码链接,对于理解本文不重要
     */
    @Bean(name = "restTemplateA")
    public RestTemplate createRestTemplate() {
        return new RestTemplate(HttpClientUtil.createHttpClient());
    }

    @Bean(name = "restTemplateB")
    public RestTemplate createRestTemplate(SimpleClientHttpRequestFactory httpRequestFactory) {
        return new RestTemplate(httpRequestFactory);
    }
}

我们想通过不同的name让Spring区分并管理这两个JavaBean,然后在其他地方通过

@Resource(name = "restTemplateA")
private RestTemplate restTemplateNew;

@Resource(name = "restTemplateB")
private RestTemplate restTemplateOld;

来使用。但是使用过程中发现引入的restTemplateNew和restTemplateOld都是restTemplateB的实例,说明restTemplateA在Config文件中加入Spring的时候,被后加入的restTemplateB覆盖掉了。
一些想法:

  后来偶然发现原因是restTemplateA和restTemplateB使用了同样的方法名createRestTemplate导致的这个问题,因为方法的参数不同,所以编译器不会报错。换了不同的名字createRestTemplateA和createRestTemplateB,就正常了,如下所示:

/**
 * 使用到的HttpClientUtil.createHttpClient()、httpRequestFactory详见文末代码链接,对于理解本文不重要
 */
@Configuration
public class HttpConfig {
    @Bean(name = "restTemplateA")
    public RestTemplate createRestTemplateA() {
    // 详见文末github代码
        return new RestTemplate(HttpClientUtil.createHttpClient());
    }

    @Bean(name = "restTemplateB")
    public RestTemplate createRestTemplateB(SimpleClientHttpRequestFactory httpRequestFactory) {
    // httpRequestFactory详见文末github代码
        return new RestTemplate(httpRequestFactory);
    }
}

  出错的地方找到了,那么原因呢?
  难道Spring生成Bean的时候根据相同的方法名,让restTemplateB覆盖掉了restTemplateA?文档上说@Bean这种方式默认的id是方法名,但是可以通过name或者value来改变。显然这种解释不对;我们将原来相同方法名的两个Bean放到两个不同的Config文件中,发现与改名一样,都起作用。


  经过反复实验,确认是方法名的锅。在Config文件中,可以所有bean都用一个方法名,然后设置不同的name,这是符合语法规范的,但是Spring创建bean的时候同一个class文件中的同名方法只有最后一个bean可以被创建(这也是为什么拆成两个文件就正常了)。
具体为什么,翻了一通源码,感觉还是看不懂。未完待续。


测试demo的地址:https://github.com/lamyoung/demo-http

上一篇 下一篇

猜你喜欢

热点阅读