Статьи

Шаблон Builder и каркас Spring

Вступление

Мне нравится использовать шаблон построителя всякий раз, когда объект имеет как обязательные, так и необязательные свойства. Но создание объектов обычно является обязанностью Spring Framework , поэтому давайте посмотрим, как вы можете использовать его, используя как Spring , так и XML-конфигурацию Spring.

Пример Строителя

Давайте начнем со следующего класса Builder.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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

Если вы используете конфигурацию на основе Spring Java, то вот как вы это сделаете:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@org.springframework.context.annotation.Configuration
public class FlexyDataSourceConfiguration {
 
    @Autowired
    private PoolingDataSource poolingDataSource;
 
    @Bean
    public Configuration configuration() {
        return new Configuration.Builder(
                UUID.randomUUID().toString(),
                poolingDataSource,
                CodahaleMetrics.BUILDER,
                BitronixPoolAdapter.BUILDER
        ).build();
    }
 
    @Bean(initMethod = "start", destroyMethod = "stop")
    public FlexyPoolDataSource dataSource() {
        Configuration configuration = configuration();
        return new FlexyPoolDataSource(configuration,
                new IncrementPoolOnTimeoutConnectionAcquiringStrategy.Builder(5),
                new RetryConnectionAcquiringStrategy.Builder(2)
        );
    }
}

Конфигурация на основе XML

Конфигурация на основе XML более многословна и не так интуитивна, как конфигурация на основе Java:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
<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"/>
 
<bean id="dataSource" class="com.vladmihalcea.flexypool.FlexyPoolDataSource" init-method="start" destroy-method="stop">
    <constructor-arg ref="configuration"/>
    <constructor-arg>
        <array>
            <bean class="com.vladmihalcea.flexypool.strategy.IncrementPoolOnTimeoutConnectionAcquiringStrategy$Builder">
                <constructor-arg value="5"/>
            </bean>
            <bean class="com.vladmihalcea.flexypool.strategy.RetryConnectionAcquiringStrategy$Builder">
                <constructor-arg value="2"/>
            </bean>
        </array>
    </constructor-arg>
</bean>

Вывод

Вы можете использовать шаблон Builder независимо от того, какой режим конфигурации Spring вы уже выбрали. Если у вас есть сомнения относительно его полезности, вот три убедительных причины, о которых вам следует знать.