开发者

Spring, autowire @Value from a database

开发者 https://www.devze.com 2022-12-26 04:15 出处:网络
I am using a properties File to store some configuration properties, that are accessed this way: @开发者_运维问答Value(\"#{configuration.path_file}\")

I am using a properties File to store some configuration properties, that are accessed this way:

@开发者_运维问答Value("#{configuration.path_file}")
private String pathFile;

Is it possible (with Spring 3) to use the same @Value annotation, but loading the properties from a database instead of a file ?


Assuming you have a table in your database stored key/value pairs:

Define a new bean "applicationProperties" - psuedo-code follows...

public class ApplicationProperties {
    @AutoWired
    private DataSource datasource;

    public getPropertyValue(String key) {
        // transact on your datasource here to fetch value for key
        // SNIPPED
    }
}

Inject this bean where required in your application. If you already have a dao/service layer then you would just make use of that.


Yes, you can keep your @Value annotation, and use the database source with the help of EnvironmentPostProcessor.

As of Spring Boot 1.3, we're able to use the EnvironmentPostProcessor to customize the application's Environment before application context is refreshed.

For example, create a class which implements EnvironmentPostProcessor:

public class ReadDbPropertiesPostProcessor implements EnvironmentPostProcessor {

    private static final String PROPERTY_SOURCE_NAME = "databaseProperties";

    private String[] CONFIGS = {
            "app.version"
            // list your properties here
    };

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        Map<String, Object> propertySource = new HashMap<>();

        try {
            // the following db connections properties must be defined in application.properties
            DataSource ds = DataSourceBuilder
                    .create()
                    .username(environment.getProperty("spring.datasource.username"))
                    .password(environment.getProperty("spring.datasource.password"))
                    .url(environment.getProperty("spring.datasource.url"))
                    .driverClassName("com.mysql.jdbc.Driver")
                    .build();

            try (Connection connection = ds.getConnection();
                 // suppose you have a config table storing the properties name/value pair
                 PreparedStatement preparedStatement = connection.prepareStatement("SELECT value FROM config WHERE name = ?")) {
                for (int i = 0; i < CONFIGS.length; i++) {
                    String configName = CONFIGS[i];
                    preparedStatement.setString(1, configName);

                    ResultSet rs = preparedStatement.executeQuery();
                    while (rs.next()) {
                        propertySource.put(configName, rs.getString("value"));
                    }

                    // rs.close();
                    preparedStatement.clearParameters();
                }
            }

            environment.getPropertySources().addFirst(new MapPropertySource(PROPERTY_SOURCE_NAME, propertySource));
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }
}

Finally, don't forget to put your spring.factories in META-INF. An example:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=
  com.baeldung.environmentpostprocessor.autoconfig.PriceCalculationAutoConfig


Although not having used spring 3, I'd assume you can, if you make a bean that reads the properties from the database and exposes them with getters.

0

精彩评论

暂无评论...
验证码 换一张
取 消