将@ConfigurationProperties与Builders一起使用的最佳方法是什么?

时间:2015-09-11 22:25:43

标签: spring spring-boot

我已经搜索过,找不到任何可以向我展示更好方法的示例,但在Spring / Spring Boot代码中,有一些通用构建器,但构建器本身似乎以编程方式应用这些属性。以下是一些尝试配置2个Oracle连接池数据源的代码:

import oracle.ucp.jdbc.PoolDataSourceFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;
import java.sql.SQLException;


@Configuration
@EnableConfigurationProperties
@ConditionalOnClass(PoolDataSourceFactory.class)
public class PersistenceAutoConfiguration {

    @Bean (name = "readWriteDataSource")
    public DataSource getReadWriteDataSource() throws SQLException {
        OracleUcpDataSourceProperties rwProperties = getReadWriteProperties();

        return OracleUcpDataSourceBuilder.create()
                .connectionFactoryClassName(rwProperties.getConnectionFactoryClassName())
                .url(rwProperties.getUrl())
                .user(rwProperties.getUser())
                .password(rwProperties.getPassword())
                .initialPoolSize(rwProperties.getInitialPoolSize())
                .minPoolSize(rwProperties.getMinPoolSize())
                .maxPoolSize(rwProperties.getMaxPoolSize())
                .connectionWaitTimeout(rwProperties.getConnectionWaitTimeout())
                .inactiveConnectionTimeout(rwProperties.getInactiveConnectionTimeout())
                .maxIdleTime(rwProperties.getMaxIdleTime())
                .build();
    }

    @Bean (name = "readOnlyDataSource")
    public DataSource getReadOnlyDataSource() throws SQLException {
        OracleUcpDataSourceProperties roProperties = getReadOnlyProperties();

        return OracleUcpDataSourceBuilder.create()
                .connectionFactoryClassName(roProperties.getConnectionFactoryClassName())
                .url(roProperties.getUrl())
                .user(roProperties.getUser())
                .password(roProperties.getPassword())
                .initialPoolSize(roProperties.getInitialPoolSize())
                .minPoolSize(roProperties.getMinPoolSize())
                .maxPoolSize(roProperties.getMaxPoolSize())
                .connectionWaitTimeout(roProperties.getConnectionWaitTimeout())
                .inactiveConnectionTimeout(roProperties.getInactiveConnectionTimeout())
                .maxIdleTime(roProperties.getMaxIdleTime())
                .build();
    }

    @ConfigurationProperties(prefix = "datasource.readwrite")
    @Bean(name = "readWriteProperties")
    protected OracleUcpDataSourceProperties getReadWriteProperties() {
        return new OracleUcpDataSourceProperties();
    }

    @ConfigurationProperties(prefix = "datasource.readonly")
    @Bean(name = "readOnlyProperties")
    protected OracleUcpDataSourceProperties getReadOnlyProperties() {
        return new OracleUcpDataSourceProperties();
    }
}

public class OracleUcpDataSourceProperties {
    private String connectionFactoryClassName;
    private String url;
    private String user;
    private String password;
    private int initialPoolSize;
    private int minPoolSize;
    private int maxPoolSize;
    private int connectionWaitTimeout;
    private int inactiveConnectionTimeout;
    private int maxIdleTime;
    private Boolean validateConnectionOnBorrow;


    public String getConnectionFactoryClassName() {
        return connectionFactoryClassName;
    }

    public void setConnectionFactoryClassName(String connectionFactoryClassName) {
        this.connectionFactoryClassName = connectionFactoryClassName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getInitialPoolSize() {
        return initialPoolSize;
    }

    public void setInitialPoolSize(int initialPoolSize) {
        this.initialPoolSize = initialPoolSize;
    }

    public int getMinPoolSize() {
        return minPoolSize;
    }

    public void setMinPoolSize(int minPoolSize) {
        this.minPoolSize = minPoolSize;
    }

    public int getMaxPoolSize() {
        return maxPoolSize;
    }

    public void setMaxPoolSize(int maxPoolSize) {
        this.maxPoolSize = maxPoolSize;
    }

    public int getConnectionWaitTimeout() {
        return connectionWaitTimeout;
    }

    public void setConnectionWaitTimeout(int connectionWaitTimeout) {
        this.connectionWaitTimeout = connectionWaitTimeout;
    }

    public int getInactiveConnectionTimeout() {
        return inactiveConnectionTimeout;
    }

    public void setInactiveConnectionTimeout(int inactiveConnectionTimeout) {
        this.inactiveConnectionTimeout = inactiveConnectionTimeout;
    }

    public int getMaxIdleTime() {
        return maxIdleTime;
    }

    public void setMaxIdleTime(int maxIdleTime) {
        this.maxIdleTime = maxIdleTime;
    }

    public Boolean getValidateConnectionOnBorrow() {
        return validateConnectionOnBorrow;
    }

    public void setValidateConnectionOnBorrow(Boolean validateConnectionOnBorrow) {
        this.validateConnectionOnBorrow = validateConnectionOnBorrow;
    }
}

import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;

import java.sql.SQLException;

public class OracleUcpDataSourceBuilder {
    private PoolDataSource pds;

    /**
     * This will grab the pool factory and initialize it.
     */
    public OracleUcpDataSourceBuilder() throws SQLException {
        pds = PoolDataSourceFactory.getPoolDataSource();
    }

    public static OracleUcpDataSourceBuilder create() throws SQLException {
        return new OracleUcpDataSourceBuilder();
    }

    public OracleUcpDataSourceBuilder connectionFactoryClassName(String connectionFactoryClassName) throws SQLException {
        pds.setConnectionFactoryClassName(connectionFactoryClassName);
        return this;
    }

    public OracleUcpDataSourceBuilder url(String url) throws SQLException {
        pds.setURL(url);
        return this;
    }

    public OracleUcpDataSourceBuilder user(String user) throws SQLException {
        pds.setUser(user);
        return this;
    }

    public OracleUcpDataSourceBuilder password(String password) throws SQLException {
        pds.setPassword(password);
        return this;
    }

    public OracleUcpDataSourceBuilder initialPoolSize(int initialPoolSize) throws SQLException {
        pds.setInitialPoolSize(initialPoolSize);
        return this;
    }

    public OracleUcpDataSourceBuilder minPoolSize(int minPoolSize) throws SQLException {
        pds.setMinPoolSize(minPoolSize);
        return this;
    }

    public OracleUcpDataSourceBuilder maxPoolSize(int maxPoolSize) throws SQLException {
        pds.setMaxPoolSize(maxPoolSize);
        return this;
    }

    public OracleUcpDataSourceBuilder connectionWaitTimeout(int connectionWaitTimeout) throws SQLException {
        pds.setConnectionWaitTimeout(connectionWaitTimeout);
        return this;
    }

    public OracleUcpDataSourceBuilder inactiveConnectionTimeout(int inactiveConnectionTime) throws SQLException {
        pds.setInactiveConnectionTimeout(inactiveConnectionTime);
        return this;
    }

    public OracleUcpDataSourceBuilder maxIdleTime(int maxIdleTime) throws SQLException {
        pds.setMaxIdleTime(maxIdleTime);
        return this;
    }

    public PoolDataSource build() {
        return pds;
    }
}

最好,我希望能够在一个地方直接将属性应用于构建器。这可能吗?我必须做出哪些改变?

...谢谢

1 个答案:

答案 0 :(得分:0)

这是你的建造者,先生

public class OracleUcpDataSourceBuilder {

private Map<String, String> properties = new HashMap<String, String>();
private static final String[] REQ_PROPERTIES = new String[] {"username", "password", "URL"};

public static OracleUcpDataSourceBuilder create() {
    return new OracleUcpDataSourceBuilder();
}

public DataSource build() {
    for (String prop : REQ_PROPERTIES) {
        Assert.notNull(properties.get(prop), "Property is required:" + prop);   
    }
    PoolDataSource result = PoolDataSourceFactory.getPoolDataSource();
    bind(result);
    return result;
}

private void bind(DataSource result) {
    MutablePropertyValues properties = new MutablePropertyValues(this.properties);
    new RelaxedDataBinder(result).bind(properties);
}

public OracleUcpDataSourceBuilder URL(String url) {
    this.properties.put("URL", url);
    return this;
}

public OracleUcpDataSourceBuilder username(String username) {
    this.properties.put("username", username);
    return this;
}

public OracleUcpDataSourceBuilder password(String password) {
    this.properties.put("password", password);
    return this;
}

}

只需像这样定义一个bean:

@Bean (name = "readOnlyDataSource")
@ConfigurationProperties(prefix = "datasource.readonly")
public DataSource getReadOnlyDataSource() {
    return OracleUcpDataSourceBuilder.create().build();
}

确保属性名称正确无误。春天将照顾其余的。

注意:我使用DataSourceBuilder或Spring作为参考。您也可以查看它的源代码。

编辑:添加了一些方法以确保配置了一些属性。但是这样,您需要手动设置这些属性以确保它们可用。