About the injection data description

1. Do not inject data through the configuration file

Using @value to dynamically inject an external Value into the Bean:

  • Injecting a normal string
  • Inject operating system properties
  • Injection expression result
  • Inject other Bean properties: Inject the name property of the Student object
  • Injecting file Resources
  • Injecting URL Resources

The auxiliary code

package com.hannpang.model;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value = "st")// Instantiate student
public class Student {
    @Value("The wu is empty")
    private String name;

    public String getName(a) {
        return name;
    }

    public void setName(String name) {
        this.name = name; }}Copy the code

Test the code for @value

package com.hannpang.model;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

@Component
public class SimpleObject {

    @Value("Inject a normal string")
    private String normal;

    // For the KEY of the attribute, see the System class description
    @Value("#{systemProperties['java.version']}")//--> use the SpEL expression
    private String systemPropertiesName; // Inject the operating system properties

    @Value("#{T(java.lang.Math).random()*80}")// Get a random number
    private double randomNumber; // Inject the result of the expression

    @Value("# {1 + 2}")
    private double sum; // Insert the sum of 1+2 resulting from the expression

    @Value("classpath:os.yaml")
    private Resource resourceFile; // Inject file resources

    @Value("http://www.baidu.com")
    private Resource testUrl; // Inject URL resources

    @Value("#{st.name}")
    private String studentName;

    // Omit the getter and setter methods

    @Override
    public String toString(a) {
        return "SimpleObject{" +
                "normal='" + normal + '\' ' +
                ", systemPropertiesName='" + systemPropertiesName + '\' ' +
                ", randomNumber=" + randomNumber +
                ", sum=" + sum +
                ", resourceFile=" + resourceFile +
                ", testUrl=" + testUrl +
                ", studentName='" + studentName + '\' ' +
                '} '; }}Copy the code

Spring test code

package com.hannpang;

import com.hannpang.model.SimpleObject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo04BootApplicationTests {

    @Autowired
    private SimpleObject so;

    @Test
    public void contextLoads(a)  { System.out.println(so); }}Copy the code
The running result is: SimpleObject{normal=' 1.8.0_172', systemPropertiesName='1.8.0_172', randomNumber=56.631954541947266, sum=3.0, ResourceFile =class path resource [os.yaml], testUrl=URL [http://www.baidu.com], studentName=' Wukong '}Copy the code

2. Inject data through the configuration file

The Value of the external configuration file is dynamically injected into the Bean via @value. There are two main types of configuration files:

  • Properties, application.yaml application.properties this file is loaded by default when Spring Boot is started
  • Custom properties file. Custom properties files are loaded via @propertysource. @propertysource can load multiple files at the same time or a single file. If the first property file and the second property file have the same key, then the key in the last property file is enabled. The path to the load file can also be configured as ${anotherfile.configinject}, which is defined in the first property file config.properties

  • Add the following test code to application.properties

    App. name= Step educationCopy the code
  • Create the first properties file, config.properties, under Resources, as follows

    Book. name= Journey to the West anotherFile. configinject=systemCopy the code
  • Create a second properties file, config_System.properties, under Resources as follows

    My goal is to use the values defined in the first properties file for the system value

    The book. The name. The author = wu chengenCopy the code

@value (${app.name}) @value (${app.name}) @value (${app.name}) @value (${app.name}) @value (${app.name}) @value (${app.name})

package com.hannpang.test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

@Component
@PropertySource(value = {"classpath:config.properties"."classpath:config_${anotherfile.configinject}.properties"})
public class LoadPropsTest {

    @Value("${app.name}")
    private String appName; // The value here is from application.properties, which is loaded by default when Spring Boot starts

    @Value("${book.name}")
    private String bookName; // Inject the first configuration external file properties

    @Value("${book.name.author}")
    private String author; // Inject the second configuration external file properties

    @Autowired
    private Environment env;  // Inject an environment variable object to store the values of the injected properties

    // Omit the getter and setter methods


    public void setAuthor(String author) {
        this.author = author;
    }


    @Override
    public String toString(a){
        StringBuilder sb = new StringBuilder();
        sb.append("bookName=").append(bookName).append("\r\n")
                .append("author=").append(author).append("\r\n")
                .append("appName=").append(appName).append("\r\n")
                .append("env=").append(env).append("\r\n")
                // Get the attribute value from eniroment
                .append("env=").append(env.getProperty("book.name.author")).append("\r\n");
        returnsb.toString(); }}Copy the code

The test code

package com.hannpang;

import com.hannpang.model.SimpleObject;
import com.hannpang.test.LoadPropsTest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo04BootApplicationTests {

    @Autowired
    private LoadPropsTest lpt;

    @Test
    public void loadPropertiesTest(a)  { System.out.println(lpt); }}Copy the code
The running result is: Env =StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[ConfigurationPropertySourcesPropertySource {name='configurationProperties'}, MapPropertySource {name='Inlined Test Properties'}, MapPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'}, OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.properties]'}, ResourcePropertySource {name='class path resource [config_system.properties]'}, ResourcePropertySource {name='class path resource [config.properties]'}]} env= Wu Cheng 'enCopy the code

3. # {... } and ${... }Demonstration of the difference between

A.The ${... }The use of the

@value (” ${app.name} “);} {app.name}; You can solve this problem by giving default values, such as @value (“${app.name: chubbyson}”).

Part of the code

// If the properties file does not have app.name, an error will be reported
// @Value("${app.name}")
// private String name;

// Use app.name to set the value, or the default value if it does not exist
@Value("${app.name: name}")
private String name;
Copy the code

B.# {... }The use of the

Part of the code directly demonstrated

// SpEL: calls the concat method of the string Hello World
@Value("#{'Hello World'.concat('! ')}")
private String helloWorld;

// SpEL: Call the getBytes method of the string, and then call the length attribute
@Value("#{'Hello World'.bytes.length}")
private String helloWorldbytes;

Copy the code

C.# {... }andThe ${... }A mixture of

The ${… #} and {… ${server.name} gets the value from the properties file and replaces it, which then becomes executing the SpEL expression {‘ server1,server2,server3 ‘.split(‘, ‘)}.

// SpEL: pass in a string (${}, ${}, ${}, ${}, ${}, ${});
@Value("#{'${server.name}'.split(',')}")
private List<String> servers;
Copy the code

${} on the outside, #{} on the inside. ${} on the inside

// SpEL: if ${} is on the outside and #{} is on the inside, this will fail
@Value("${#{'HelloWorld'.concat('_')}}")
private List<String> servers2;
Copy the code
The answer is no. Spring executes ${} earlier than #{}. In this case, Spring will try to find #{' HelloWorld '.concat(' _ ')} from the property, so it will definitely find it, and as we know above if it can't find it, then it will report an error. So ${} on the outside, #{} on the inside is illegalCopy the code

[D]

  • # {… } is used to execute the SpEl expression and assign the content to the property
  • The ${… } is used to load values from external properties files
  • # {… } and ${… } can be mixed, but it must be #{} outside and ${} inside

4.@Value gets the value compared to @configurationProperties

@ConfigurationProperties @Value
function Batch injection of properties in the configuration file Specify one by one
Loose binding (loose syntax) support Does not support
SpEL Does not support support
JSR303 data verification support Does not support
Complex type encapsulation support Does not support

They can get values for both yML and properties;

  • If we just need to get the Value of an item in the configuration file in some business logic, use @value;

  • If we specifically wrote a Javabeans to map to a configuration file, we would use @ConfigurationProperties directly;

Part of the code for data verification

@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
   //lastName must be in mailbox format
    @Email
    private String lastName;

Copy the code

5. @ImportResourceImporting a Configuration File

This is not recommended

There is no Spring configuration file in Spring Boot, and the configuration file written by us cannot be automatically identified.

To make the Spring configuration file work, load it in. The @ImportResource annotation is on a configuration class

@ImportResource(locations = {"classpath:beans.xml"}) Import Spring's configuration file to make it workCopy the code

Write configuration file information

<?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.xsd">
    <bean id="helloService" class="com.hanpang.springboot.service.HelloService"></bean>
</beans>
Copy the code

Just to get the idea, we don’t really use it

6.@Configurationannotations

The way SpringBoot recommends adding components to a container; The full annotated approach is recommended

The @configuration class is applied to a class and acts as an XML Configuration file

Add a component to the container using @bean and apply it to the method

/ * * *@Configuration: indicates that the current class is a configuration class. <bean id="helloService" ><bean/> <bean/> class="com.hanpang.springboot.service.HelloService"></bean> */
@Configuration
public class MyAppConfig {

    // Add the return value of the method to the container; The default ID for this component in the container is the method name
    @Bean
    public HelloService helloService02(a){
        System.out.println("Config class @bean adds components to the container...");
        return newHelloService(); }}Copy the code

Bean injection is too cumbersome, and we prefer to use scanning


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
 
import com.wx.dao.IUserDao;
import com.wx.dao.UserDaoImpl;
 
// Use this annotation to indicate that the class is a Spring configuration, equivalent to a traditional ApplicationContext.xml
@Configuration
// Equivalent to the 
       tag in the configuration file, scan for the annotations of the classes below these packages
@ComponentScan(basePackages="com.hanpang.dao,com.hanpang.service")
public class SpringConfig {
	// Use this annotation to indicate that it is a Bean object, equivalent to < Bean > in XML
	// The default id value of the bean is the method name userDao
	/* @bean public HelloService helloService02(){system.out.println (" @bean added component to container...") ); return new HelloService(); } * /
}
Copy the code

The appendix

The random number

The ${random value}, ${random.int}, ${random.long}
${random.int(10)}, ${random.int[1024.65536]}
Copy the code