35

Per connettersi a CouchDB, utilizzo ektorp.Spring: utilizzo del pattern builder per creare un bean

Il modo di costruire un'istanza EKTORP HttpClient è quello di utilizzare builder:

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

Sono relativamente nuovo a primavera. Si prega di avvisarmi su come posso configurare un HttpClient nel mio contesto per crearlo tramite lo Builder.

Un modo per farlo è con @Configuration. Ci sono altre opzioni?

risposta

42

Puoi provare a implementare FactoryBean interfaccia:

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; 
}} 

E aggiungere a config seguente definizione di fagioli:

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

Poi si può iniettare questo fagiolo ad altri fagioli, sarà risolto come StdHttpClient esempio.

3

Controllare la documentazione Spring FactoryBean e FactoryMethod.

1

Sebbene non esplicito per il tuo caso; è possibile estendere un builder se espone le proprietà tramite i metodi del modello di fagiolo standard set. vale a dire se prendiamo il org.apache.httpcomponents:httpclientHttpClientBuilder come esempio potremmo avere la seguente:

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; 
    } 

} 

Ora qualsiasi metodo esposto da HttpClientBuilder è accessibile per il bean di fabbrica. Una configurazione come il seguente è ora possibile:

<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> 
5

volta ho inciampato sulla stessa questione, quando stavo sviluppando flexy-pool (a reactive connection pool sizing utility), così ho scritto an article sia con un e un esempio basato su XML Java-based.

In sostanza, a partire dal seguente Builder:

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; 
    } 
} 

Utilizzando la configurazione di Java-based è straight-forward:

@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(); 
    } 
} 

Ma è anche possibile utilizzare la configurazione basata su XML pure:

<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"/> 
+0

Leggere il tuo articolo. Mi è piaciuto in questo modo e l'ho trovato unico. Potresti aiutarmi a capire il costrutto degli ultimi due costruttori-arg? Non sono stato in grado di trovare alcun aiuto sul costrutto BUILDER utilizzato lì. – rajneesh2k10

+1

È un costruttore che prende altri builder per risolvere alcune dipendenze. –

+0

Oh ... Quindi "BUILDER" è di proprietà di "CodahaleMetrics" e "BitronixPoolAdapter", se non errato. – rajneesh2k10