Spring: использование шаблона Builder для создания компонента - PullRequest
37 голосов
/ 13 июля 2010

Я использую ektorp для подключения к CouchDB.

Способ создания экземпляра ektorp HttpClient заключается в использовании шаблона построителя:

HttpClient httpClient = new StdHttpClient.Builder()
                                .host("mychouchdbhost")
                                .port(4455)
                                .build();

Я относительно новичок в весне. Пожалуйста, посоветуйте мне, как мне настроить HttpClient в моем контексте, чтобы создать его через Builder.

Один из способов сделать это - @Configuration. Есть еще варианты?

Ответы [ 4 ]

46 голосов
/ 13 июля 2010

Вы можете попробовать реализовать интерфейс FactoryBean:

public class HttpFactoryBean implements FactoryBean<HttpClient>{

private String host;
private int port;


public HttpClient getObject() throws Exception {
    return new StdHttpClient.Builder()
                            .host(host)
                            .port(port)
                            .build();
}

public Class<? extends HttpClient> getObjectType() {
    return StdHttpClient.class;
}

public boolean isSingleton() {
    return true;
}

public void setHost(String host) {
    this.host = host;
}

public void setPort(int port) {
    this.port = port;
}}

И добавить в конфигурацию следующее определение компонента:

<beans ..."> 
   <bean name="myHttpClient" class="HttpFactoryBean">
       <property name="port" value="8080"/>
       <property name="host" value="localhost"/>
   </bean>
</beans>

Затем вы можете внедрить этот компонент в другие компоненты, он будет разрешен как StdHttpClient экземпляр.

6 голосов
/ 14 августа 2014

Однажды я наткнулся на ту же проблему, когда разрабатывал flexy-pool (утилита определения размера пула реактивных соединений) , поэтому я написал статью с обоими на основе Java и пример на основе XML.

В основном, начиная со следующего Строителя:

public final class Configuration<T extends DataSource> extends ConfigurationProperties<T, Metrics, PoolAdapter<T>> {

    public static final long DEFAULT_METRIC_LOG_REPORTER_PERIOD = 5;

    public static class Builder<T extends DataSource> {
        private final String uniqueName;
        private final T targetDataSource;
        private final PoolAdapterBuilder<T> poolAdapterBuilder;
        private final MetricsBuilder metricsBuilder;
        private boolean jmxEnabled = true;
        private long metricLogReporterPeriod = DEFAULT_METRIC_LOG_REPORTER_PERIOD;

        public Builder(String uniqueName, T targetDataSource, MetricsBuilder metricsBuilder, PoolAdapterBuilder<T> poolAdapterBuilder) {
            this.uniqueName = uniqueName;
            this.targetDataSource = targetDataSource;
            this.metricsBuilder = metricsBuilder;
            this.poolAdapterBuilder = poolAdapterBuilder;
        }

        public Builder setJmxEnabled(boolean enableJmx) {
            this.jmxEnabled = enableJmx;
            return this;
        }

        public Builder setMetricLogReporterPeriod(long metricLogReporterPeriod) {
            this.metricLogReporterPeriod = metricLogReporterPeriod;
            return this;
        }

        public Configuration<T> build() {
            Configuration<T> configuration = new Configuration<T>(uniqueName, targetDataSource);
            configuration.setJmxEnabled(jmxEnabled);
            configuration.setMetricLogReporterPeriod(metricLogReporterPeriod);
            configuration.metrics = metricsBuilder.build(configuration);
            configuration.poolAdapter = poolAdapterBuilder.build(configuration);
            return configuration;
        }
    }

    private final T targetDataSource;
    private Metrics metrics;
    private PoolAdapter poolAdapter;

    private Configuration(String uniqueName, T targetDataSource) {
        super(uniqueName);
        this.targetDataSource = targetDataSource;
    }

    public T getTargetDataSource() {
        return targetDataSource;
    }

    public Metrics getMetrics() {
        return metrics;
    }

    public PoolAdapter<T> getPoolAdapter() {
        return poolAdapter;
    }
}

Использование конфигурации на основе Java просто:

@org.springframework.context.annotation.Configuration
public class FlexyDataSourceConfiguration {

    @Bean
    public Configuration configuration() {
        return new Configuration.Builder(
                UUID.randomUUID().toString(),
                poolingDataSource,
                CodahaleMetrics.BUILDER,
                BitronixPoolAdapter.BUILDER
        ).build();
    }
}

Но вы также можете использовать конфигурацию на основе XML:

<bean id="configurationBuilder" class="com.vladmihalcea.flexypool.config.Configuration$Builder">
    <constructor-arg value="uniqueId"/>
    <constructor-arg ref="poolingDataSource"/>
    <constructor-arg value="#{ T(com.vladmihalcea.flexypool.metric.codahale.CodahaleMetrics).BUILDER }"/>
    <constructor-arg value="#{ T(com.vladmihalcea.flexypool.adaptor.BitronixPoolAdapter).BUILDER }"/>
</bean>

<bean id="configuration" factory-bean="configurationBuilder" factory-method="build"/>
3 голосов
/ 13 июля 2010

Пожалуйста, проверьте документацию Spring FactoryBean и FactoryMethod.

1 голос
/ 11 февраля 2014

Пока не явно для вашего случая; можно расширить компоновщик, если он предоставляет свойства с помощью стандартных методов bean pattern set. то есть если мы возьмем org.apache.httpcomponents:httpclient HttpClientBuilder в качестве примера, у нас может быть следующее:

public class HttpClientFactoryBean
        extends HttpClientBuilder
        implements InitializingBean,
                   FactoryBean<HttpClient> {

    private HttpClient value;

    @Override
    public void afterPropertiesSet() throws Exception {
        this.value = build();
    }

    @Override
    public HttpClient getObject() throws Exception {
        return value;
    }

    @Override
    public Class<?> getObjectType() {
        return HttpClient.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

}

Теперь любой метод, предоставляемый HttpClientBuilder, доступен для вашего фабричного компонента. Теперь возможна конфигурация, такая как следующая:

<beans id="httpClient" class="com.drunkendev.factory.HttpClientFactoryBean">
  <beans name="defaultCredentialsProvider" ref="credentialsProvider"/>
  <beans name="targetAuthenticationStrategy">
    <util:constant static-field="org.apache.http.impl.client.TargetAuthenticationStrategy.INSTANCE"/>
  </beans>
</beans>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...