Spring Boot 2 learning notes: Container Management

Keywords: Java Spring Spring Boot

In the previous section, we simply used SpringBoot to complete HelloWorld. This section describes in depth how to use SpringBoot for container management, such as registering components in the container, reading resources, etc

2. Container management

2.1 registering components using configuration classes

In Spring, we use Spring's xml configuration file to register bean s and add components to the container

<bean id="person" class="com.lin.pojo.Person">
    <property name="name" value="Mike"/>
</bean>

In SpringBoot, xml configuration files have been discarded, and components can be registered by using Java configuration classes. The steps are as follows

① Create a MyConfig class and decorate it with the annotation @ Configuration

@Configuration//This is a configuration class
public class MyConfig {

}

② Replace the label with a function in the configuration class and decorate the method with @ Bean. By default, the method name is used as the component name, the return type is used as the component class, and the return value is used as the instance in the container. You can specify the component name using @ Bean("component name")

@Configuration
public class MyConfig {
    //It is equivalent to registering a bean with id of person, type of com.lin.pojo.Person and instance of new Person("Mike")
    @Bean //@Bean("component name") can specify the component name
    public Person person(){
        return new Person("Mike"); 
    }
}

③ Get components in the main program

@SpringBootApplication
public class Application {
    public static void main(String[] args)
    {
        ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
        Object person = run.getBean("person");//Get by id
        Person bean = run.getBean(Person.class);//Get by type
        System.out.println(person==bean);//true indicates that it is a singleton
    }
}

2.2 using the auto scan registration component

In 2.1, it is equivalent to manually registering components. Another method is to let SpringBoot scan automatically

① Use the @ Component annotation on the class of the component to be added

@Component
public class Person {
    @Value("Mike") //Using @ Value injection Value, the underlying layer is injected through reflection
    String name;
}

② Get components in the main program

@SpringBootApplication
public class Application {
    public static void main(String[] args)
    {
        ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
        Object person = run.getBean("person");
        Person bean = run.getBean(Person.class);
        System.out.println(person==bean);//It is also a single case
    }
}

Why can you scan automatically without explicitly configuring the scan path? Because it has been configured by default in the main program annotation @ SpringBootApplication. The principle is as follows:

Check @ SpringBootApplication and find that there are three annotations to modify @ SpringBootApplication. The scanning path represented by * * @ ComponentScan is the package of the main program and the following sub packages**

[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-zo1ydquf-1630583138609)( https://i.loli.net/2021/09/02/CkdNlwYG57Lh19j.png )]

Then, it is feasible to replace @ SpringBootApplication with these three annotations in the main program

//When the following three annotations are used together, they are equivalent to @ SpringBootApplication!!
@SpringBootConfiguration//Represents that this is the configuration class of SpringBoot
@EnableAutoConfiguration//Load all eligible @ Configuration configurations into the IoC container.
@ComponentScan("com.lin")//Here is the package name of the main program
public class Application {
    public static void main(String[] args)
    {
        ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
        Object person = run.getBean("person");
        Person bean = run.getBean(Person.class);
    }
}

2.3 register components using @ Import

@Import can be used on any component already in the IOC container to register the classes in the Class type array into the container

You can apply @ Import to the main program class, because the Application class itself is also a component, which is registered by @ SpringBootApplication

@SpringBootApplication
@Import({Person.class})//Register the Person component
public class Application {
    public static void main(String[] args)
    {
        ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
        Person person = run.getBean("com.lin.pojo.Person",Person.class);//id is the full class name
        Person bean = run.getBean(Person.class);
        bean.setName("Mike");
        person.setName("Mike");
        System.out.println(bean==person);
    }
}

2.5 how to select the three methods of registering components?

Best practice: in most cases, the configuration class in 2.1 is used, and the more convenient automatic scanning in 2.2 can also be used.

If you want to Import components from a third-party package, you need to use @ Import of 2.3. Because it is impossible to modify the source code of the third-party package, add @ Component to it

2.6 using @ ImportResource to import native configuration files

Although it is recommended to register components in the form of configuration classes in SpringBoot, it is also feasible to register bean s using the original Spring.xml configuration file. Just use @ ImportResource on any component that is already in the IOC container

@SpringBootApplication 
@ImportResource("classpath:/beans.xml")//Import profile
public class Application {
    public static void main(String[] args)
    {
        ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
        Person person = run.getBean("person",Person.class);
        Person bean = run.getBean(Person.class);
    }
}

2.7 two methods of binding with properties file

How do I read the properties and encapsulate their contents into a JavaBean? Previously, the following java code was used to load, traverse, and then encapsulate

public class getProperties {
     public static void main(String[] args) throws FileNotFoundException, IOException {
         Properties pps = new Properties();
         pps.load(new FileInputStream("a.properties"));//load file
         Enumeration enum1 = pps.propertyNames();//Get configuration file key
         while(enum1.hasMoreElements()) {//ergodic
             String strKey = (String) enum1.nextElement();
             String strValue = pps.getProperty(strKey);
             System.out.println(strKey + "=" + strValue);
             //Encapsulate into JavaBean s.
         }
     }
 }

In SpringBoot, you can * * directly use annotations to bind configuration files to beans * * * *, such as writing in application.properties

//person corresponds to the prefix attribute of the annotation, and name corresponds to the attribute in the Bean
person.name=test 

2.7.1 use @ ConfigurationProperties

This annotation must be used on components registered in the IOC container, that is, it is valid only if any of the previous methods of adding components are used, and the annotation is injected through set

@ConfigurationProperties(prefix = "person") //Premise: Person has been registered
public class Person {
     String name;
    public Person(String name) {
        this.name = name;
    }
    public Person() {
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
        System.out.println("Called set");
    }
}

@SpringBootApplication
public class Application {
    public static void main(String[] args)
    {
        ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
        Person person = run.getBean("person",Person.class);
        System.out.println(person); //Person{name='test'}
    }

Here, I choose to register the Person class through the method in the configuration class (2.1), and then use @ ConfigurationProperties. I find that the parameterized structure will be called first, and then the value in the properties will be injected through set, so finally name = "test"

2.7.2 use @ EnableConfigurationProperties + @ConfigurationProperties

As shown in 2.5.1, on the premise of using @ ConfigurationProperties, you can directly use @ EnableConfigurationProperties on the configuration class. It has two functions: first, register the class, and then bind the properties file

@Configuration
//Used on the configuration class, it has two functions: first, register Person, and then bind
@EnableConfigurationProperties(Person.class)
public class MyConfig {
    //@ Bean registration is not required
}

@SpringBootApplication
public class Application {
    public static void main(String[] args)
    {
        ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
        //The default component name registered through @ EnableConfigurationProperties is: class name lowercase - full class name
        Person person = run.getBean("person-com.lin.pojo.Person",Person.class);
        Person bean = run.getBean(Person.class);
        System.out.println(person);//Person{name='test'}
        System.out.println(bean);//Person{name='test'}
    }
}

Summary: if you want to use the functions of SpringBoot, such as binding with properties, the premise is that the components have been registered in the container, then the three registration methods are extremely important

Posted by mattison on Thu, 02 Sep 2021 23:46:56 -0700