Basic introduction - understand the principle of automatic configuration [medium]

Posted by cyrixware on Tue, 21 Dec 2021 15:28:05 +0100

Part I: Introduction to basics -- understanding the principle of automatic configuration [i]

1, Container function

1. Add @ Configuration component

Case test:

(1) Configuration class

package org.apache.springboot.config;

import org.apache.springboot.bean.Pet;
import org.apache.springboot.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 *The @ Bean annotation is used in the configuration class to register components for the container on the method. By default, it is also single instance
 * The configuration class itself is also a component
 */
@Configuration //Tell SpringBoot that this is a configuration class = = configuration file
public class MyConfig {
    @Bean //Add components to the container. Take the method name as the id of the component. The return type is the component type. The returned value is the instance of the component in the container
    public User user01(){
       // User zhangsan = new User("zhangsan", 18);
        //The user component depends on the Pet component
        return new User("zhangsan",18);
    }

    @Bean("tom")  //Adding the tag "tom" mainly replaces the method name. Printing will only print out "tom", not tomcatPet. However, if this tag is not added to the "Bean" annotation, it will print the method name, such as user01 method

    public Pet tomcatPet(){
        return new Pet("tomcat");
    }
}

(2) startup

package org.apache.springboot;

import org.apache.springboot.bean.Pet;
import org.apache.springboot.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;

/**
 * Main program class
 * @SpringBootApplication: This is a SpringBoot application
 */
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
public class MainApplication {

    public static void main(String[] args) {
        //1. Return to our IOC container
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
        //2. View the information in the container
        String[] names = run.getBeanDefinitionNames();
        for (String name :names){
            System.out.println(name);
        }
        //Get components from container
        Pet tom01 = run.getBean("tom", Pet.class);
        Pet tom02 = run.getBean("tom", Pet.class);
        System.out.println("Components:"+(tom01==tom02));

        MyConfig bean = run.getBean(MyConfig.class);
        System.out.println(bean);
    }
}

Printout:

When we want to call the method under the @ bean annotation of the configuration class, such as the user01 method.

You only need to add @ Configuration(proxyBeanMethods = true) to the configuration class

Then get the method in the startup class, such as:

When we start, we find that the printout is true, indicating that we have obtained the method

Specify the proxyBeanMethods = true parameter in the annotation, which adopts the Full mode. Ensure that the returned component of each @ Bean method is single instance no matter how many times it is called, that is, no matter how many times it is called by the external registration method of this component in the configuration class, it will get the single instance object in the previous registration container

Description:

If the @ Configuration(proxyBeanMethods = true) proxy object calls the method. SpringBoot always checks whether the component is in the container.

If @ Configuration(proxyBeanMethods = false), the method is not called by the proxy object. The returned result is false. How many times each @ Bean method is called, the returned component is newly created

Component dependencies must use the Full mode default. Other default Lite modes

 

2, Automatic configuration [source code analysis] - principle of automatic package rules

1,@SpringBootConfiguration

Represents the current configuration class

2,@ComponentScan

Specify which Spring annotations to scan

3,@EnableAutoConfiguration

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}

3.1,@AutoConfigurationPackage

Auto configuration package? The default package rule is specified

Check the source code, enter "AutoConfigurationPackages" with ctrl+n, and batch register the register method

In fact, in the source code, there is a registerBeanDefinitions method with two parameters:

@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
			register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
		}

Annotation metadata: meta information of annotations, mainly used to register AutoConfigurationPackage

@Import(AutoConfigurationPackages.Registrar.class)  //Import a component into the container
public @interface AutoConfigurationPackage {}

//Use the Registrar to import a series of components into the container
//Import all components under a specified package? Under the package of MainApplication.

From debug, you can see where the meta information of the register annotation is explained

In fact, it is really assigned to the startup class

At the same time, it uses new packageimports (metadata) Getpackagenames(), get meta package name

Therefore, import all components under the specified package into the package where MainApplication is located

Topics: Java Javascript