35

J'utilise ektorp pour me connecter à CouchDB.Spring: Utilisation du pattern builder pour créer un bean

La façon de construire une instance EKTORP HttpClient est d'utiliser modèle de constructeur:

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

Je suis relativement nouveau au printemps. S'il vous plaît me conseiller sur la façon dont je peux configurer un HttpClient dans mon contexte pour le créer via le Builder.

Une façon de le faire est avec @Configuration. Y a-t-il d'autres options?

Répondre

42

Vous pouvez essayer de mettre en œuvre l'interface 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; 
}} 

Et ajouter à config suivante définition de haricot:

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

Vous pouvez alors injecter ce haricot à l'autre des haricots, il sera résolu comme StdHttpClient exemple.

3

Veuillez vérifier la documentation Spring FactoryBean et FactoryMethod.

1

Bien que non explicite pour votre cas; Il est possible d'étendre un générateur s'il expose des propriétés via des méthodes de modèle de haricot standard set. à savoir si nous prenons le org.apache.httpcomponents:httpclientHttpClientBuilder comme un exemple, nous pourrions avoir les éléments suivants:

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

} 

Maintenant, toute méthode exposée par HttpClientBuilder est accessible à votre grain de l'usine. Une configuration telle que la suivante est maintenant possible:

<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

Je suis tombé une fois sur la même question, quand je développais flexy-pool (a reactive connection pool sizing utility), donc je l'ai écrit an article à la fois un Java et un exemple basé sur XML.

En fait, à partir du constructeur suivant:

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

En utilisant la configuration Java est directe:

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

Mais vous pouvez également utiliser la configuration XML ainsi:

<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

Lisez votre article. J'ai aimé ce chemin et l'ai trouvé unique. Pourriez-vous m'aider à comprendre la construction des deux derniers constructor-arg? Je n'ai pas pu trouver d'aide sur la construction BUILDER utilisée ici. – rajneesh2k10

+1

C'est un constructeur qui prend d'autres constructeurs pour résoudre certaines dépendances. –

+0

Oh ... Ainsi, le "BUILDER" est la propriété de "CodahaleMetrics" et "BitronixPoolAdapter" si ce n'est pas le cas. – rajneesh2k10