Detailed explanation of @AutoConfiguration annotation

@AutoConfigurationIt belongs to the annotation under the package springboot. It provides us with a lot , such as about caching and timing tasks . You will find that these are basically used for decoration. In this article, we will thoroughly understand what it does and how to apply it.autoconfigurespringbootAutoConfigurationcacheCacheAutoConfigurationquartzQuartzAutoConfigurationAutoConfiguration@AutoConfiguration@AutoConfiguration

1. Observe @AutoConfiguration source code

There are three meta-annotations in the source code:

  • @Target({ElementType.TYPE}): Use range interfaces, classes, enumerations, annotations
  • @Retention(RetentionPolicy.RUNTIME): @Retention is used to modify the life cycle of the annotation. RetentionPolicy.RUNTIME means that it is not only saved in the class file, but still exists after jvm loads the class file; it is always valid!
  • @Documented: @Documented and @Deprecated annotations look a bit similar. @Deprecated is used to mark a certain class or method. It is not recommended to continue to use it. @Documented can only be used on annotations. If an annotation @B is annotated by @Documented , then the class modified by @B will display @B when generating the Javadoc document.

In addition to meta-annotations, there are three annotations:

  • @Configuration: This is the most commonly used annotation in development. It belongs to @Componentthe extended annotation of annotations @Controller、@Service. The functions of several annotations are the same. Just add this annotation to the class, and then springbootstart the project within the scanning range. At this time, the class modified by the annotation will be created through a parameterless constructor, and then stored in the spring container.
  • @AutoConfigureBefore: It is generally used together @Configuration, mainly used to modify the class, and then you can specify that the class is loaded into the container before a certain class.
  • @AutoConfigureAfter: Same @AutoConfigureBeforeas the function, he specifies that the class will be loaded into the container after a certain class.

See the example below for specific usage!

@Target({
    
    ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration(
    proxyBeanMethods = false
)
@AutoConfigureBefore
@AutoConfigureAfter
public @interface AutoConfiguration {
    
    
    @AliasFor(
        annotation = Configuration.class
    )
    String value() default "";

    @AliasFor(
        annotation = AutoConfigureBefore.class,
        attribute = "value"
    )
    Class<?>[] before() default {
    
    };

    @AliasFor(
        annotation = AutoConfigureBefore.class,
        attribute = "name"
    )
    String[] beforeName() default {
    
    };

    @AliasFor(
        annotation = AutoConfigureAfter.class,
        attribute = "value"
    )
    Class<?>[] after() default {
    
    };

    @AliasFor(
        annotation = AutoConfigureAfter.class,
        attribute = "name"
    )
    String[] afterName() default {
    
    };
}

@AutoConfiguration is actually a composite annotation. Because an automatic configuration class often needs to add a lot of annotations, springboot combines some frequently used annotations together, so that one annotation can have the function of three annotations. Specifically, how does he achieve the aggregation of annotations? The reason is that it depends on @AliasForannotations. The @AliasFor annotation is to play the role of an annotation passing value. If you want to learn more about @AliasFor, you can read this article of mine:

https://blog.csdn.net/weixin_43888891/article/details/126962698?spm=1001.2014.3001.5501

insert image description here

Two, @Configuration

@ConfigurationWe often use annotations, but we rarely use them in this way @Configuration(proxyBeanMethods = false). The default here proxyBeanMethodsis true, but it is set to false, so what does this attribute do?

@ConfigurationIt belongs springto the annotations. If you are interested, you can look at the explanation in the spring source code: https://github.com/spring-projects/spring-framework/blob/main/spring-context/src/main/java/org/springframework /context/annotation/Configuration.java

The explanation in the source code is not in Chinese, and it is generally incomprehensible. We directly draw conclusions through code experiments:

When it is true, the object we get in the container is always the same, even if we call the method of creating the object, the object we get is still the same. But when there are multiple instances, if we call the method of creating the object, it will not be the same.

(1) Customize a class for testing

public class TestBean1 {
    
    
    @Override
    public String toString() {
    
    
        return super.toString() + "--我是TestBean1";
    }

    public TestBean1() {
    
    
        System.out.println("TestBean1构造器执行了");
    }
}

(2) Add configuration class

@Configuration(proxyBeanMethods = true)
public class Myconfig {
    
    

    @Bean
    public TestBean1 testBean1() {
    
    
        return new TestBean1();
    }
}

(3) Add test class

@RestController
public class CommonController {
    
    

    @Autowired
    private Myconfig myconfig;

    @Autowired
    private TestBean1 testBean1;

    @RequestMapping("/import")
    public void printImportBeanInfo() {
    
    
        System.out.println(testBean1);
        System.out.println(myconfig.testBean1());
    }
}

(4) Access the interface, and it is concluded that the object obtained from the container and directly accessing the testBean1 method is an object, which is the so-called proxy

insert image description here
(5) set to false@Configuration(proxyBeanMethods = false)

Apparently it's not an object anymore.

insert image description here

三、@AutoConfigureBefore

(1) Customize two configuration classes

@Configuration
public class Config1 {
    
    

    public Config1() {
    
    
        System.out.println("Config1构建了");
    }
}

@Configuration
public class Config2 {
    
    

    public Config2() {
    
    
        System.out.println("Config2构建了");
    }
}

(2) Start the project test: the default is to create Config1 first and then create Config2

insert image description here

Now there is a demand for @Config2 to be loaded first. Maybe someone should say @Order annotation at this time. In fact, it is not. The @Order value may affect the priority of the injection point, but please note that it does not Will affect the singleton startup sequence. Regarding @order, I specially compiled an article for reference and study!
https://blog.csdn.net/weixin_43888891/article/details/127481825

(3) The premise of using @AutoConfigure related annotations is that it must be an automatic configuration class. Maybe sometimes the shit luck gives you an illusion that the configuration is really successful.

Adding the @AutoConfigureBefore(Config1.class) annotation on Config2 is to tell him that I want to inject the container before Config1. Only adding the annotation and starting the project again will find that it has no effect!

insert image description here

There is spring.factories under the autoconfigure package. This file is configured with automatic configuration classes, and springboot will read this file. We can also define spring.factories on our own projects, so that our configuration classes can take effect for @AutoConfigureAfter annotations up.

insert image description here
(4) Customize spring.factories

insert image description here

The first line is fixed, and the latter is the full class name. Although only Config2 uses annotations, the requirement is to sort with Config1, so both of them have to be added.

Some people may have doubts about this. I don’t use the @AutoConfigureBefore annotation. Can I modify the startup sequence of these two configuration classes only through the configuration under spring.factories? The answer is no! ! ! I have also verified this through experiments!

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.gzl.cn.springbootcache.config.Config2,\
com.gzl.cn.springbootcache.config.Config1

(5) Test, successfully resolved

insert image description here

四、@AutoConfigureAfter

@AutoConfigureAfter and @AutoConfigureBefore are actually the same, I won't demonstrate here, if you are interested, you can refer to the above to practice.

五、@AutoConfigureOrder

This is also possible! Of course, the premise is also to configure spring.factories

@Configuration
@AutoConfigureOrder(2)
public class Config1 {
    
    

    public Config1() {
    
    
        System.out.println("Config1构建了");
    }
}

@Configuration
@AutoConfigureOrder(1)
public class Config2 {
    
    

    public Config2() {
    
    
        System.out.println("Config2构建了");
    }
}

6. Source code analysis

In fact, the key code is still in AutoConfigurationImportSelector. After the automatic configuration class is loaded from spring.factories, it will be sorted according to the conditions. The last line of code in the selectImports() method is as follows:

insert image description here

Then we will come to this place, which is actually sorted in three steps:

  1. alphabetically first
  2. Sort by @AutoConfigureOrder
  3. Sort by @AutoConfigureBefore and @AutoConfigureAfter

insert image description here
From the order of configuration above, we can know that the final decision lies in the two annotations of @AutoConfigureAfter and @AutoConfigureBefore.

When we don't set spring.factories, there are no these two classes at all!

insert image description here

Guess you like

Origin blog.csdn.net/weixin_43888891/article/details/127473290#comments_27843205