The main function of Spring Boot is to simplify the development of Spring applications. Developers only need a small amount of code to create a Spring application, and the core idea to achieve this goal is convention over configuration.

Convention Over Configuration is a software design paradigm that aims to improve development efficiency by reducing the number of configurations or the difficulty of understanding them.

To sum up a conclusion:

Spring Boot automatically loads beans outside the classpath using spring. Factories are used to help configure beans automatically

Some experiments with Springboot Autoconfig

A springboot project, springbootautoconfig. Test. Config the package and start the class package is no longer under the same path, so this package under the note will not take effect, such as bean managed to spring management

@ Configuration / / open Configuration @ EnableConfigurationProperties (HelloProperties. Class) / / open using a mapping entity object ConditionalOnClass(testhello.class)// ConditionalOnProperty (prefix =)// ConditionalOnProperty (TestHello)// ConditionalOnProperty (prefix = Zxp. hello value = "flag") public Class HelloAutoConfiguration {@autoWired private HelloProperties helloProperties; ConditionalOnMissingBean(testhello.class) ConditionalOnMissingBean SpringIoc public TestHello HelloService () {system.out.println (">>>The TestHello Not Found, Execute Create New Bean."); TestHello testHello = new TestHello(helloProperties.getName(),helloProperties.getFlag()); return testHello; }}Copy the code
@ConfigurationProperties(prefix = "zxp.hello")
@Data
public class HelloProperties {
    private String name;
    private String flag;
}
Copy the code
public class TestHello { String name; String flag; public TestHello(String name, String flag) { this.name = name; this.flag = flag; } public String print(){ String msg = "name is "+name + " " + "flag is "+flag; System.out.println(msg); return msg; }}Copy the code

After testing, the project failed to start and an error was reported at the following location:

@RestController public class TempController { @Autowired TestHello testHello; @requestMapping ("/test/boot") public String boot(){return testhello.print (); }}Copy the code

Create a meta-INF path under Resources and create the Spring.factories file

Configure the automatic configuration of the custom Starter org.springframework.boot.autoconfigure.EnableAutoConfiguration=springbootautoconfig.test.config.HelloAutoConfigurationCopy the code

Try to start again error again

- Bean method 'helloService' not loaded because @ConditionalOnProperty (zxp.hello) did not find property 'flag'
Copy the code

The reason is that if zXP.hello. flag is not configured, how can an error be reported

@conditionalonProperty // Initialize the configuration class if it exists (prefix = "zxP. hello",// Hello value = "flag")Copy the code

Add in application.properties

zxp.hello.flag=2
Copy the code

There you go. Access controller

name is null flag is 1
Copy the code

Add another configuration as well

zxp.hello.name=zhang xp
Copy the code

Access to the controller

name is zhang xp flag is 1
Copy the code

SpringBoot Autoconfig notes

ConditionalOnXxx can decide whether to perform automatic configuration according to the conditions

@ ConditionalOnBean: when the existence condition of the specified Bean SpringIoc container @ ConditionalOnSingleCandidate: When specifying the Bean in SpringIoc container is only one, or even though there are multiple specify preferred Bean @ ConditionalOnMissingBean: when SpringIoc existence condition of the specified Bean container not @ ConditionalOnClass: When the existence condition of the specified Class SpringIoc container @ ConditionalOnMissingClass: when SpringIoc container Class conditions specified does not exist @ ConditionalOnExpression: As a condition of judgment based on SpEL expression @ ConditionalOnJava: based on the JVM version as a condition of judging @ ConditionalOnJndi: in JNDI to exist to find the location specified @ ConditionalOnResource: Class path if there is a specified value @ ConditionalOnProperty: specify the attributes for the specified value @ ConditionalOnNotWebApplication: The current project is not the conditions of the Web project @ ConditionalOnWebApplication: the current project is the condition of the Web project @ AutoConfigureBefore @ AutoConfigureAfter @ AutoConfigureOrderCopy the code
public @interface ConditionalOnProperty { String[] value() default {}; String prefix() default ""; String[] name() default {}; // Property name prefix, optional String[] name() default {}; String havingValue() default ""; String havingValue() default ""; Boolean matchIfMissing() default false; // Whether the property can be loaded without it. If true, the property will load normally without it; Boolean relaxedNames() default true; // Can be loosely matched, so far I do not know how to use}Copy the code

SpringBoot autoconfig principle

Springboot start kind comments @ SpringBootApplication introducing @ EnableAutoConfiguration and introducing @ Import (AutoConfigurationImportSelector. Class)

AutoConfigurationImportSelector class called SpringFactoriesLoader. LoadFactoryNames method scan all the meta-inf/spring jars. The factories, the following code:

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you " + "are using a custom packaging, make sure that file is correct."); return configurations; } public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; public static List<String> loadFactoryNames(Class<? > factoryType, @nullable ClassLoader ClassLoader) {... Enumeration<URL> urls = (classLoader ! = null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); result = new LinkedMultiValueMap<>(); while (urls.hasMoreElements()) {Copy the code

The contents of the Spring. factories file in the spring-boot-autoconfigure package

... work.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ Org. Springframework. Boot. Autoconfigure. Closer. RabbitAutoConfiguration. \...Copy the code

Contains all of the auto-configured bean configurations that Spring adds to it, and these beans are loaded into the Spring context when they meet the criteria for auto-configuration

eg:

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ RabbitTemplate.class, Channel.class })
@EnableConfigurationProperties(RabbitProperties.class)
@Import(RabbitAnnotationDrivenConfiguration.class)
public class RabbitAutoConfiguration {
Copy the code

RabbitTemplate will report an error, why not a class that doesn’t exist here? 1, the jar compile time this class is some, can guarantee to compile 2, look at the comments of the ConditionalOnClass annotations

The classes that must be present. Since this annotation is parsed by loading class bytecode, > it is safe to specify classes here that may ultimately not be on the classpath, only if this annotation is directly on the affected component and not if this annotation is used as a composed, meta-annotation. In order to use this annotation as a meta-annotation, only use the name attribute. Returns: the classes that must be present

Classes that must be present. Because this annotation is resolved by loading class bytecode, it is safe to specify classes that may not end up on the classpath here, provided that the annotation is directly on the affected component and not used as a meta-annotation for composition. To use this annotation as a meta-annotation, use only the name attribute.

starter

Starter is a way of organizing maven dependencies into a single project to avoid introducing too many Maven configurations