为了账号安全,请及时绑定邮箱和手机立即绑定

当我们在@Bean 中创建新类,并在另一个@Bean 中使用@Bean 时会发生什么

当我们在@Bean 中创建新类,并在另一个@Bean 中使用@Bean 时会发生什么

qq_遁去的一_1 2023-06-04 15:27:27
我有豆子:@Beanpublic Map<String, Integer> currenciesCodesMap(@Value("${readTimeoutMillis}") int readTimeout,                                               @Value("${connectTimeoutMillis}") int connectTimeout,                                               UriFactory uriFactory) {    System.out.println("currenciesCodesMap");    RestTemplate restTemplate = getRestTemplate(readTimeout + 1, connectTimeout + 1);    List<Map> maps = Arrays.asList(Objects.requireNonNull(restTemplate.getForObject(uriFactory.getProgressiveCurrencyRates(), Map[].class)));        Map<String, Integer> currenciesCodesMap = maps.stream().collect(Collectors.toMap(                map -> (String) map.get("code"),                map -> (Integer) map.get("id")        ));}@Beanpublic RestTemplate codesConverterRestTemplate(@Value("${readTimeoutMillis}") int readTimeout,                                                   @Value("${connectTimeoutMillis}") int connectTimeout,                                                   UriFactory uriFactory) {        System.out.println("codesConverterRestTemplate");        return getRestTemplate(readTimeout, connectTimeout);    }@Beanpublic RestTemplate getRestTemplate(int readTimeout, int connectTimeout) {        CloseableHttpClient httpClient = HttpClientBuilder.create().disableCookieManagement().build();        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);        factory.setReadTimeout(readTimeout);        factory.setConnectTimeout(connectTimeout);        System.out.println("getRestTemplate");        return new RestTemplate(factory);    }我不想在每个 bean 中创建新的 RestTemplate,所以我决定在另一个 bean 中创建它,并将第三个 bean 注入到前两个 bean 中。在启动时,我看到(使用 System.out.println)我的 bean 只创建了一个(因为它们是单例),但我不明白它是怎么回事,因为我使用不同的参数在前两个 bean 中调用第三个 bean。所以我的问题是:这整个事情是如何运作的。new RestTemplate(factory) 将被调用多少次,如果我在两个具有不同参数的地方使用它,它怎么可能是对第三个 bean 的一次调用。以这种方式创建 RestTemplate 是一种好方法吗
查看完整描述

1 回答

?
慕村9548890

TA贡献1884条经验 获得超4个赞

类@Configuration不会在每次一个注解为 的方法@Bean调用另一个注解为 的方法时实例化一个新对象@Bean。考虑这个例子:


@Configuration

public class TestConfig {


    @Bean

    public String bean2(){

        String bean = bean1("bean2");

        System.out.println("bean2: " + bean);

        return bean;

    }


    @Bean

    public String bean3(){

        String bean = bean1("bean3");

        System.out.println("bean3: " + bean);

        return bean;

    }


    @Bean

    public String bean1(@Autowired(required = false) String name){

        System.out.println("bean1 " + name);

        return name;

    }

}

输出如下,因为bean2()是先执行的:


bean1 bean2

bean2: bean2

bean3: bean2

这是相关文件:

换句话说,当您定义一个 bean 定义并将其限定为单例时,Spring IoC 容器会创建该 bean 定义定义的对象的一个实例。这个单个实例存储在此类单例 bean 的缓存中,并且对该命名 bean 的所有后续请求和引用都返回缓存的对象。下图显示了单例作用域的工作原理:

在这种情况下,注释为的方法@Bean 一个 bean 定义。

还:

所有 @Configuration 类都在启动时使用 CGLIB 进行子类化。在子类中,子方法在调用父方法并创建新实例之前首先检查容器中是否有任何缓存的(范围内的)bean。

换句话说,@Bean无论参数如何,每次调用带注释的方法都应该返回相同的 bean。depends-on在您的情况下,我认为它是未定义的行为,因为除非您使用or之类的选项,否则不能保证实例化的顺序SmartLifecycle


查看完整回答
反对 回复 2023-06-04
  • 1 回答
  • 0 关注
  • 123 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信