猿问

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

我有豆子:


@Bean

public 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")

        ));

}


@Bean

public RestTemplate codesConverterRestTemplate(@Value("${readTimeoutMillis}") int readTimeout,

                                                   @Value("${connectTimeoutMillis}") int connectTimeout,

                                                   UriFactory uriFactory) {

        System.out.println("codesConverterRestTemplate");

        return getRestTemplate(readTimeout, connectTimeout);

    }

@Bean

public 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 是一种好方法吗


qq_遁去的一_1
浏览 167回答 1
1回答

慕村9548890

类@Configuration不会在每次一个注解为 的方法@Bean调用另一个注解为 的方法时实例化一个新对象@Bean。考虑这个例子:@Configurationpublic 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 bean2bean2: bean2bean3: bean2这是相关文件:换句话说,当您定义一个 bean 定义并将其限定为单例时,Spring IoC 容器会创建该 bean 定义定义的对象的一个实例。这个单个实例存储在此类单例 bean 的缓存中,并且对该命名 bean 的所有后续请求和引用都返回缓存的对象。下图显示了单例作用域的工作原理:在这种情况下,注释为的方法@Bean 是一个 bean 定义。还:所有 @Configuration 类都在启动时使用 CGLIB 进行子类化。在子类中,子方法在调用父方法并创建新实例之前首先检查容器中是否有任何缓存的(范围内的)bean。换句话说,@Bean无论参数如何,每次调用带注释的方法都应该返回相同的 bean。depends-on在您的情况下,我认为它是未定义的行为,因为除非您使用or之类的选项,否则不能保证实例化的顺序SmartLifecycle。
随时随地看视频慕课网APP

相关分类

Java
我要回答