SpringBoot learning notes 02 - Common annotations and automatic assembly

Posted by stephenf33 on Thu, 03 Mar 2022 14:21:25 +0100

1. Common spring annotations

1.1 automatic assembly

1.1.1 @Configuration

Since Spring 3.0, it has supported a better Configuration method: the Configuration method based on Java classes. The @ Configuration annotation indicates that this is a Configuration class, and its bottom layer is @ Component (that is, the bean object of this class will also be taken over by the Spring container).

Function of proxybeanMethods attribute: specify whether the method modified by @ bean annotation is proxied. true indicates that the method is proxied (the underlying cglib, that is, the method cannot be private or final modified). Each call to the method will directly obtain the bean object in the container rather than actually execute the method; false means that the method is not proxied, and a new object (corresponding to full and lite modes) will be obtained each time it is called.

1.1.2 @Bean

With @ Configuration, the function of XML Configuration injection can be realized, and the effect is the same as that of

<beans>
	<bean>...</bean>
    <bean>...</bean>
</beans>

Similarly, when using @ Bean annotation, it means that the object returned by the method is loaded into the Spring container. When using @ Bean to decorate the method, you should pay attention to:

  1. Method takes the return value, and the return type is the type of bean to be managed;
  2. The method name is the default bean name, which can be customized by using the name attribute of @ Bean;
  3. Method can take parameters, so the parameters passed in at this time must also be bean s managed by the Spring container.

1.1.3 @Value

This annotation is used to read properties from the configuration file, such as application There is a configuration in yaml

server:
	port: 8000

If we use this annotation to modify the method parameter public void test(@Value("${server.port}") address), the attribute 8000 will be automatically injected into the address variable.

@There are two ways to locate the Value property:

  • ${property: default_value}: read the value in the configuration file (such as *. properties, *.yaml)

  • #{obj.property?: default_value}: read the property value of the bean object managed in the container.

Suppose an object is declared as follows:

@Component
public class ServerProperty {
@Value("${server.url}")
private String url;

// getter and setter
// ...
}

@Component
public class Server {
	@Value("#{serverProperty.url}")
	private String url;
}

The first @ Value refers to reading the property from the configuration file and injecting it into the bean object named serverProperty, while the second @ Value reads the data from the bean object named serverProperty and injects it into the server.

Note: @ Value needs to set null default Value to a variable of String type @ Value("${server.url: #{null}").

1.1.4 @ConfigurationProperties

Its function is to map the values of Java class properties to the configuration file, that is, through the @ ConfigurationProperties annotation, we can use the configuration files such as properties or yaml to manage all property values, and then map and load them into Java objects. The prefix attribute of the annotation specifies the unique identification name in the configuration file.

1.1.5 @EnableConfigurationProperties

@The function of the ConfigurationProperties annotation is only to load the value mapping of the configuration file into the Java object, but this object is no different from ordinary Java objects and is not managed by the Spring container. The function of @ EnableConfigurationProperties is to turn these classes modified by @ ConfigurationProperties into bean objects managed by the Spring container, Adding @ Component to the class modified by @ ConfigurationProperties can also make it managed by the Spring container.

1.1,6 @Conditional

Spring4.0 provides @ Conditional annotation and if then... Else to manage the registration of Bean objects.

Using @ Conditional annotation needs to be combined with an interface called Condition to achieve results. The Condition interface has only one method, matches:

public interface Condition {
	boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

This matches method is the concrete code implementation of if... then... else semantic logic.

@The Conditional annotation has an attribute value, which is a class array class <? Extensions condition > [], whose logic is that when the execution result of the macros method of all element classes in value is true, it is agreed to register the Bean object.

@Conditional can be used to modify classes (@ component and @ Configuration, etc.) or methods (@ Bean), and has many extensions, such as

  • @ConditionalOnBean: the specified Bean object exists in the container;
  • @ConditionalOnMissingBean: the specified Bean object does not exist in the container;
  • ...

1.1.7 @Import

This annotation is used to integrate all bean configurations defined in the @ Configuration annotation. Its function is similar to importing multiple XML Configuration files into a single xml file.

@Import, combined with the ImportSelector interface, can dynamically select the imported Configuration class (@ Configuration modifier class). Its use is somewhat similar to the combination of @ Conditional and Condition interfaces. For example, @ Import(AutoConfigurationImportSelector.class) is used to load all autoconfiguration classes in SpringBoot. The ImportSelector interface provides the following methods:

public interface ImportSelector {
	// ...
    
	String[] selectImports(AnnotationMetadata importingClassMetadata);
}

The string array returned by this method selectImports is the class to be imported with the @ Import annotation.

1.1.8 @EnableAutoConfiguration

This annotation is decorated with @ Import(AutoConfigurationImportSelector.class), which specifies a series of components that will be automatically loaded into the Spring container.

1.2 Web

1.2.1 @RequestMapping

Map the HTTP request to the processing method modified by the annotation. The derived annotations are:

  • @GetMapping: the essence is that @ RequestMapping specifies the GET method to receive HTTP GET requests;
  • @PostMapping: essentially, @ RequestMapping specifies the POST method to receive HTTP POST requests;
  • @PutMapping: the essence is that @ RequestMapping specifies the PUT method to receive HTTP PUT requests;
  • @DeleteMapping: essentially, @ RequestMapping specifies the DELETE method to receive HTTP DELETE requests;
  • ...

1.2.2 @RequestBody

This annotation is used to read the request body data of Http request (when content type is application/json), and then bind this part of data to the method parameters modified by this annotation. At most one parameter in the same method can be modified by @ RequestBody.

Note: cannot be used with GET request.

1.2.3 @ResponseBody

This annotation can modify methods and other annotations, indicating that the object returned by the method is converted into a certain format and written into the response body of the response message. It is generally used to return Json data.

1.2.4 RestController

This annotation is generally used to modify a class, which is essentially @ Controller + @ResponseBody. Therefore, it aggregates the routing function of @ Controller and the function of @ ResponseBody - all methods on the class will return data in Json format.

1.2.5 @RequestParam

This annotation is used to receive the query parameters of Http requests. The source can be divided into two parts:

  • URL of GET method;
  • form data of POST method (when content type is application/x-www-form-urlencoded).

1.2.6 @PathVariable

This annotation is used to parse the URL template. If we design a REST style URL, it is as follows:

@RequestMapping("xxx.com/items/{id}")
public String getItemById(@PathVariable("id") String id) {}

When accessing "xxx.com/items/100", the method parameters of the method getItemById can be directly parsed to get "100".

2. Spring Boot automatic assembly principle

Spring Boot will automatically assemble a series of components (bean objects) at startup. Because it automatically loads these components, developers can use the functions and services provided by Spring Boot without any configuration, and can use them in application Override the default configuration in properties. The principle of its implementation is mainly through JavaConfig and several common annotations mentioned above.

2.1 how to carry out automatic assembly

There is a combined annotation @ SpringBootApplication on the startup class of Spring Boot:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
    // ...
}

After ignoring the meta annotation of Java, there are mainly three annotations left:

  • @SpringBootConfiguration: note that this is a Configuration class, which is essentially a @ Configuration;
  • @EnableAutoConfiguration: automatically inject qualified bean s into the Spring container;
  • @ComponentScan: specify the path to scan the package.

The core of automatic assembly is mainly realized through @ EnableAutoConfiguration. The source code of this annotation is as follows:

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

Here is a combination of @ Import and ImportSelector interface implementation classes. See autoconfigurationimportselector Class's selectImports method:

public String[] selectImports(AnnotationMetadata annotationMetadata) {
    // Check whether automatic assembly is disabled, that is, whether the value of "spring.boot.enableautoconfiguration" is true
    if (!isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    }
    AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
    return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

In the getAutoConfigurationEntry method, we call the getCandidateConfigurations method, which uses SpringFactoriesLoader (based on Java SPI mechanism expansion) to read spring-boot-autoconfigure-xxx.. Meta-inf / spring.jar package According to the contents of the factories file, get the fully qualified name of the automatic assembly class and load it.

spring. The contents of the factories file are as follows. SpringFactoriesLoader parses it into a map < string, list < string > > structure, in which key is classified according to the function of components, and value is the fully qualified name of a series of corresponding automatic assembly classes.

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
...

# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.data.redis.RedisUrlSyntaxFailureAnalyzer,\
...

# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
...

Since @ SpringBootApplication is decorated by @ EnableAutoConfiguration annotation, all auto assembly classes corresponding to EnableAutoConfiguration (XXXXAutoConfiguration.class) will be loaded and injected into the Spring container.

2.2 how to inject attributes of automatic assembly class

Developers in application The function of overriding the default configuration in properties is actually realized by mapping the contents of the configuration file to the members on the automatic assembly class. The process of injecting properties into the automatic assembly class (xxxmaautoconfiguration. Class) uses the above-mentioned annotations: @ ConfigurationProperties and @ EnableConfigurationProperties. With kafkaautoconfiguration Class as an example:

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(KafkaTemplate.class)
@EnableConfigurationProperties(KafkaProperties.class)
@Import({ KafkaAnnotationDrivenConfiguration.class, KafkaStreamsAnnotationDrivenConfiguration.class })
public class KafkaAutoConfiguration {
    private final KafkaProperties properties;
    // ...
}

This class itself is a configuration class. There are many methods modified by @ bean annotation to generate components managed by Spring container. It is modified by @ EnableConfigurationProperties and injected with kafkaproperties Class, and kafkaproperties Class is also modified by @ ConfigurationProperties, that is, all properties are finally provided by the configuration file, which also explains why developers can use it in application Override the default configuration in properties.

@ConfigurationProperties(prefix = "spring.kafka")
public class KafkaProperties {
    // ...
}

3. References

  1. Understand the description and use of @ Conditional annotation
  2. @Annotation usage and source code analysis of Import and ImportSelector
  3. @Functions and differences between ResponseBody and @ RestController
  4. Springboot (IV) -- do you know how @ EnableConfigurationProperties works

Topics: Java Spring Spring Boot