Explanation of Spring Loading Configuration and Reading Multiple Properties Files

  • 2021-07-06 11:01:42
  • OfStack

The following configuration files in the form of Properties usually exist in a system

1. Database configuration files demo-db. properties:


database.url=jdbc:mysql://localhost/smaple 
database.driver=com.mysql.jdbc.Driver 
database.user=root 
database.password=123 

2. Message service configuration files demo-mq. properties:


#congfig of ActiveMQ 
mq.java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory 
mq.java.naming.provider.url=failover:(tcp://localhost:61616?soTimeout=30000&connectionTimeout=30000)?jms.useAsyncSend=true&timeout=30000 
mq.java.naming.security.principal= 
mq.java.naming.security.credentials= 
jms.MailNotifyQueue.consumer=5

3. Remote invoked configuration files demo-remote. properties:


remote.ip=localhost 
remote.port=16800 
remote.serviceName=test 

1. Multiple Properties configuration files need to be loaded in the system

Application scenario: There is more than one Properties configuration file, and multiple Properties files need to be loaded at the same time when the system starts.

Configuration mode:


<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation=" 
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 
  <!--  Read multiple configuration files into a container and give them to Spring Management  --> 
  <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
    <property name="locations"> 
      <list> 
       <!--  Multiple addressing methods are supported here: classpath And file --> 
       <value>classpath:/opt/demo/config/demo-db.properties</value> 
       <!--  Recommended use file So that configuration and code can be separated  --> 
       <value>file:/opt/demo/config/demo-mq.properties</value> 
       <value>file:/opt/demo/config/demo-remote.properties</value> 
      </list> 
    </property> 
  </bean> 
  <!--  Use MQ Configuration in  --> 
  <bean id="MQJndiTemplate" class="org.springframework.jndi.JndiTemplate"> 
    <property name="environment"> 
      <props> 
        <prop key="java.naming.factory.initial">${mq.java.naming.factory.initial}</prop> 
        <prop key="java.naming.provider.url">${mq.java.naming.provider.url}</prop> 
        <prop key="java.naming.security.principal">${mq.java.naming.security.principal}</prop> 
        <prop key="java.naming.security.credentials">${mq.java.naming.security.credentials}</prop> 
        <prop key="userName">${mq.java.naming.security.principal}</prop> 
        <prop key="password">${mq.java.naming.security.credentials}</prop> 
      </props> 
    </property> 
  </bean> 
</beans> 

We can also extract List from the configuration:


<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation=" 
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 
  <!--  Put multiple profile locations in the list  --> 
  <bean id="propertyResources" class="java.util.ArrayList"> 
    <constructor-arg> 
      <list> 
       <!--  Multiple addressing methods are supported here: classpath And file --> 
       <value>classpath:/opt/demo/config/demo-db.properties</value> 
       <!--  Recommended use file So that configuration and code can be separated  --> 
       <value>file:/opt/demo/config/demo-mq.properties</value> 
       <value>file:/opt/demo/config/demo-remote.properties</value> 
      </list> 
    </constructor-arg> 
  </bean> 
  <!--  Read the configuration file into the container and give it to Spring Management  --> 
  <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
    <property name="locations" ref="propertyResources" /> 
  </bean> 
  <!--  Use MQ Configuration in  --> 
  <bean id="MQJndiTemplate" class="org.springframework.jndi.JndiTemplate"> 
    <property name="environment"> 
      <props> 
        <prop key="java.naming.factory.initial">${mq.java.naming.factory.initial}</prop> 
        <prop key="java.naming.provider.url">${mq.java.naming.provider.url}</prop> 
        <prop key="java.naming.security.principal">${mq.java.naming.security.principal}</prop> 
        <prop key="java.naming.security.credentials">${mq.java.naming.security.credentials}</prop> 
        <prop key="userName">${mq.java.naming.security.principal}</prop> 
        <prop key="password">${mq.java.naming.security.credentials}</prop> 
      </props> 
    </property> 
  </bean> 
</beans> 

2. Integrate multiple dispersed Properties under multi-engineering

Scenario: There are multiple profiles in the project group, but these profiles are used in multiple places, so they need to be loaded separately.

The configuration is as follows:


<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:p="http://www.springframework.org/schema/p" 
  xsi:schemaLocation=" 
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 
  <!--  Will DB Property profile location in the list  --> 
  <bean id="dbResources" class="java.util.ArrayList"> 
    <constructor-arg> 
    <list> 
      <value>file:/opt/demo/config/demo-db.properties</value> 
    </list> 
    </constructor-arg> 
  </bean> 
  <!--  Will MQ Property profile location in the list  --> 
  <bean id="mqResources" class="java.util.ArrayList"> 
    <constructor-arg> 
    <list> 
      <value>file:/opt/demo/config/demo-mq.properties</value> 
    </list> 
    </constructor-arg> 
  </bean> 
  <!--  Use Spring Load and manage DB Property profile  --> 
  <bean id="dbPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
    <property name="order" value="1" /> 
    <property name="ignoreUnresolvablePlaceholders" value="true" />  
    <property name="locations" ref="dbResources" /> 
  </bean> 
  <!--  Use Spring Load and manage MQ Property profile  --> 
  <bean id="mqPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
    <property name="order" value="2" /> 
    <property name="ignoreUnresolvablePlaceholders" value="true" />  
    <property name="locations" ref="mqResources" /> 
  </bean> 
  <!--  Use DB Configuration properties in  --> 
  <bean id="rmsDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"  
    p:driverClassName="${demo.db.driver}" p:url="${demo.db.url}" p:username="${demo.db.username}"  
    p:password="${demo.db.password}" pp:maxActive="${demo.db.maxactive}"p:maxWait="${demo.db.maxwait}"  
    p:poolPreparedStatements="true" p:defaultAutoCommit="false"> 
  </bean> 
  <!--  Use MQ Configuration in  --> 
  <bean id="MQJndiTemplate" class="org.springframework.jndi.JndiTemplate"> 
    <property name="environment"> 
      <props> 
        <prop key="java.naming.factory.initial">${mq.java.naming.factory.initial}</prop> 
        <prop key="java.naming.provider.url">${mq.java.naming.provider.url}</prop> 
        <prop key="java.naming.security.principal">${mq.java.naming.security.principal}</prop> 
        <prop key="java.naming.security.credentials">${mq.java.naming.security.credentials}</prop> 
        <prop key="userName">${mq.java.naming.security.principal}</prop> 
        <prop key="password">${mq.java.naming.security.credentials}</prop> 
      </props> 
    </property> 
  </bean> 
</beans> 

Note: The order attribute represents its loading order, while ignoreUnresolvablePlaceholders is whether to ignore the unresolved Placeholder. If multiple PropertyPlaceholderConfigurer are configured, it needs to be set to true. Here 1 definitely needs to set these two parameters in this way.

3. Inject values directly into Properties configuration files in Bean

Scenario: Bean requires direct injection of values from the Properties configuration file. For example, the following code needs to get the values in demo-remote. properties above:


public class Client() { 
  private String ip; 
  private String port; 
  private String service; 
} 

The configuration is as follows:


<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="<a href="http://www.springframework.org/schema/beans" rel="external nofollow" rel="external nofollow" >http://www.springframework.org/schema/beans</a>" 
 xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance" rel="external nofollow" >http://www.w3.org/2001/XMLSchema-instance</a>" 
 xmlns:util="<a href="http://www.springframework.org/schema/util" rel="external nofollow" rel="external nofollow" >http://www.springframework.org/schema/util</a>" 
 xsi:schemaLocation=" 
 <a href="http://www.springframework.org/schema/beans" rel="external nofollow" rel="external nofollow" >http://www.springframework.org/schema/beans</a> <a href="http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" rel="external nofollow" >http://www.springframework.org/schema/beans/spring-beans-3.0.xsd</a> 
 <a href="http://www.springframework.org/schema/util" rel="external nofollow" rel="external nofollow" >http://www.springframework.org/schema/util</a> <a href="http://www.springframework.org/schema/util/spring-util-3.0.xsd" rel="external nofollow" >http://www.springframework.org/schema/util/spring-util-3.0.xsd</a>"> 
 <!--  This loading method can be used in code through @Value Annotation for injection ,  
  You can assign the configuration as a whole to Properties Class variable of type, you can also take out the 1 Item assignment to String Class variable of type  --> 
 <!-- <util:properties/>  Labels can only be loaded 1 You can use multiple tags when multiple properties files need to be loaded  --> 
 <util:properties id="remoteSettings" location="file:/opt/demo/config/demo-remote.properties" />  
 <!-- <util:properties/>  The implementation class of the tag is PropertiesFactoryBean ,  
  Object that directly uses this class's bean Configure and set its locations Property can be reached 1 One and above 1 Sample the purpose of loading multiple configuration files  --> 
 <bean id="settings"  
class="org.springframework.beans.factory.config.PropertiesFactoryBean"> 
  <property name="locations"> 
 <list> 
  <value>file:/opt/rms/config/rms-mq.properties</value> 
  <value>file:/opt/rms/config/rms-env.properties</value> 
 </list> 
  </property> 
 </bean> 
</beans> 

The Annotation used in the Client class is as follows:


import org.springframework.beans.factory.annotation.Value; 
public class Client() { 
  @Value("#{remoteSettings['remote.ip']}") 
  private String ip; 
  @Value("#{remoteSettings['remote.port']}") 
  private String port; 
  @Value("#{remoteSettings['remote.serviceName']}") 
  private String service; 
}

4. Class variables of type Properties exist in Bean

Application scenario: When Properties type class variable exists in Bean, it needs to be initialized by injection

1. Configuration mode: We can use the configuration mode in (3), but the comments in the code are modified as follows


import org.springframework.beans.factory.annotation.Value; 
import org.springframework.beans.factory.annotation.Autowired; 
public class Client() { 
  @Value("#{remoteSettings}") 
  private Properties remoteSettings; 
} 

2. Configuration: You can also use Bean declared in xml and inject


#congfig of ActiveMQ 
mq.java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory 
mq.java.naming.provider.url=failover:(tcp://localhost:61616?soTimeout=30000&connectionTimeout=30000)?jms.useAsyncSend=true&timeout=30000 
mq.java.naming.security.principal= 
mq.java.naming.security.credentials= 
jms.MailNotifyQueue.consumer=5
0

The code is as follows:


#congfig of ActiveMQ 
mq.java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory 
mq.java.naming.provider.url=failover:(tcp://localhost:61616?soTimeout=30000&connectionTimeout=30000)?jms.useAsyncSend=true&timeout=30000 
mq.java.naming.security.principal= 
mq.java.naming.security.credentials= 
jms.MailNotifyQueue.consumer=5
1

The above scenarios are particularly useful in a project cluster and require flexible use of the above configurations.

In many cases, we need to configure a few properties in the configuration file and inject them into bean, which provides org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer Class, it is convenient for us to use annotations to directly inject configurations in properties files.

Let's take a look at how to operate:

First, create a new maven project and add the spring dependency to the pom file, as shown in the pom. xml file:


#congfig of ActiveMQ 
mq.java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory 
mq.java.naming.provider.url=failover:(tcp://localhost:61616?soTimeout=30000&connectionTimeout=30000)?jms.useAsyncSend=true&timeout=30000 
mq.java.naming.security.principal= 
mq.java.naming.security.credentials= 
jms.MailNotifyQueue.consumer=5
2

To automatically inject the configuration in the properties file, you need to add in the spring configuration file org.springframework.beans.factory.config.PropertiesFactoryBean And org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer Instance configuration of:

The following spring configuration file appContext. xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context-3.0.xsd ">
  <!-- bean annotation driven -->
  <context:annotation-config />
  <context:component-scan base-package="cn.outofmemory.hellospring.properties.annotation">
  </context:component-scan>
  <bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="locations">
      <list>
        <value>classpath*:application.properties</value>
      </list>
    </property>
  </bean>
  <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
    <property name="properties" ref="configProperties" />
  </bean>  
</beans>

In this configuration file, we configured annotation scanning, and configProperties Examples and propertyConfigurer Instance. In this way, we can automatically inject configuration into the java class. Let's look at how to do it in the java class:


#congfig of ActiveMQ 
mq.java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory 
mq.java.naming.provider.url=failover:(tcp://localhost:61616?soTimeout=30000&connectionTimeout=30000)?jms.useAsyncSend=true&timeout=30000 
mq.java.naming.security.principal= 
mq.java.naming.security.credentials= 
jms.MailNotifyQueue.consumer=5
4

Automatic injection requires the @ Value annotation, the format of which is #{configProperties['mysql.url']} Where configProperties is the beanId we configured in appContext. xml, and mysql. url is the configuration entry in the properties file.

The properties file reads as follows:


#congfig of ActiveMQ 
mq.java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory 
mq.java.naming.provider.url=failover:(tcp://localhost:61616?soTimeout=30000&connectionTimeout=30000)?jms.useAsyncSend=true&timeout=30000 
mq.java.naming.security.principal= 
mq.java.naming.security.credentials= 
jms.MailNotifyQueue.consumer=5
5

Finally, we need to test whether there is any problem with the above writing under 1, as follows: App. java file content:


#congfig of ActiveMQ 
mq.java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory 
mq.java.naming.provider.url=failover:(tcp://localhost:61616?soTimeout=30000&connectionTimeout=30000)?jms.useAsyncSend=true&timeout=30000 
mq.java.naming.security.principal= 
mq.java.naming.security.credentials= 
jms.MailNotifyQueue.consumer=5
6

In the main method, appContext is first declared, and then an instance of MySQLConnectionInfo injected automatically is obtained, and then printed out, and the running program will output the values configured in the configuration file

Summarize


Related articles: