This is the 31st day of my participation in the August Text Challenge.More challenges in August
1 Understanding Spring Boot automatic configuration
The Spring framework provides several ways to configure a Bean object,XML configuration, annotation configuration, and JavaConfig configuration classes. As Spring projects add functionality, the configuration gets bigger and harder to manage. Therefore, automatic configuration is adopted in Spring Boot to solve the problem of excessive configuration management in the Spring framework.
1 the Java configuration
Solutions to simplify XML configuration in Spring include:
-
Component Scan: Spring automatically discovers beans created in the application context.
-
AutoWired: Spring automatically creates dependencies between beans.
-
Java code configuration beans are implemented in JavaConfig mode.
Use a custom configuration class for columns:
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
/** * to register interceptors, our own interceptors need to be registered here to take effect *@param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
/ / column, such as
// addPathPatterns("/**") intercepts all requests
ExcludePathPatterns ("/login", "/register") indicate things other than login and registration
registry.addInterceptor(this.getMyInterceptor()).addPathPatterns("/ * *").excludePathPatterns("/login"."/register");
}
@Bean
public MyInterceptor getMyInterceptor(a) {
return new MyInterceptor();
}
/** * used to configure static resources such as HTML, JS, CSS, etc., columns such as when using swagger document *@param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {}}Copy the code
The 1@Configuration annotation marks this class as Spring’s Configuration class.
2 Hand over the interceptor class to the Spring container for management via the @Bean annotation tag
2 conditional beans
Spring Boot can control Bean registration to the container depending on different conditions.
1 annotations @ Conditional
Conditional annotations can do different Bean object injection based on different conditions. Similar to state patterns in design patterns.
Common notes:
Conditions of annotation | Conditions that |
---|---|
@ConditionalOnBean | A Bean is instantiated only when an object exists in context |
@ConditionalOnClass | A Bean is instantiated only when the class is on the classpath |
@ConditionalOnExpression | A Bean is instantiated only when the expression is True |
@ConditionalOnMissingBean | A Bean is instantiated only when there is no object in the context |
@ConditionalOnMissingClass | A Bean is instantiated when a class does not exist on the classpath |
@ConditionalOnNotWebApplication | A Bean is instantiated only if it is not a Web application |
Conditional annotations use case columns
Goal:
The target Bean object is created when the password configuration item exists in application.properties and the value is true.
password=123456
Copy the code
The custom class implements the Condition interface
public class MyController implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
if (environment.containsProperty("password")) {
String password = environment.getProperty("password");
System.out.println("Password = =" + password);
return "123456".equals(password);
}
return false; }}Copy the code
ConditionContext, the first parameter, is a context interface. The source code is as follows
public interface ConditionContext {
/** Returns the BeanDefinitionRegistry object for the Bean definition, which can be checked with BeanDefinitionRegistry */
BeanDefinitionRegistry getRegistry(a);
/ * * returns ConfigurableListableBeanFactory object, used to check whether B diamine, and check the Bean properties * /
@Nullable
ConfigurableListableBeanFactory getBeanFactory(a);
/** Return Environment to check if the Environment variable exists and read its value */
Environment getEnvironment(a);
/** Read and check the resources loaded by the ResourceLoader it returns */
ResourceLoader getResourceLoader(a);
/** Returns a ClassLoader object to load and check if the class exists */
@Nullable
ClassLoader getClassLoader(a);
}
Copy the code
The second parameter AnnotatedTypeMetadata.
public interface AnnotatedTypeMetadata {
MergedAnnotations getAnnotations(a);
// Determine if the @bean annotated method has other specific annotations
default boolean isAnnotated(String annotationName) {
return this.getAnnotations().isPresent(annotationName);
}
@Nullable
default Map<String, Object> getAnnotationAttributes(String annotationName) {
return this.getAnnotationAttributes(annotationName, false);
}
@Nullable
default Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
MergedAnnotation<Annotation> annotation = this.getAnnotations().get(annotationName, (Predicate)null, MergedAnnotationSelectors.firstDirectlyDeclared());
return! annotation.isPresent() ?null : annotation.asAnnotationAttributes(Adapt.values(classValuesAsString, true));
}
@Nullable
default MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName) {
return this.getAllAnnotationAttributes(annotationName, false);
}
@Nullable
default MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
Adapt[] adaptations = Adapt.values(classValuesAsString, true);
return (MultiValueMap)this.getAnnotations().stream(annotationName).filter(MergedAnnotationPredicates.unique(MergedAnnotation::getMetaTypes)).map(M ergedAnnotation::withNonMergedAttributes).collect(MergedAnnotationCollectors.toMultiValueMap((map) -> {return map.isEmpty() ? null: map; }, adaptations)); }}Copy the code
Spring4 deploys profiles for multiple environments using the ProfileCondition class
class ProfileCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if(attrs ! =null) {
for (Object value : attrs.get("value")) {
if (context.getEnvironment().acceptsProfiles(Profiles.of((String[]) value))) {
return true; }}return false;
}
return true; }}Copy the code
3 ConditionalConfig
Use the @conditionnal annotation method to specify conditions in value. The Bean is instantiated only when the Spring container meets the criteria, otherwise the Bean is not registered.
4 Combination notes
A composite annotation is a combination of existing annotations to produce a new annotation. Using this new annotation is equivalent to using all the annotations in the composite annotation.
Such as the @spring BootApplication annotation on the boot class.
@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 {
...
Copy the code
3 Spring Boot Automatic configuration process
Spring Boot automatic configuration relies on the @enableAutoConfiguration annotation
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
Copy the code
@ EnableAutoConfiguration annotations in the main is @ Import (AutoConfigurationImportSelector. Class) annotations, use the Enable – AutoConfigurationImportSelector , @enableAutoConfiguration, and The Spring Boot application loads all the qualified @Configuration classes into the current Spring container.
1 @enableAutoConfiguration Remarks
Spring Boot automatically by the @ EnableAutoConfiguration start Spring application context configuration, import a AutoConfigurationImportSelector class, AutoConfigurationImportSelector reads Fetch the fully qualified name of the class whose key is EnableAutoConfiguration under spring.factories.
Partial source 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;
}
Copy the code
The main purpose of the spring-factories setup is to tell Spring Boot which *AutoConfiguration classes the stareter needs to load, which are the beans or functions you really want to automatically register. Then, we implement a spring.factories class annotated with @Configuration, and the starter definition is complete.
The getSpringFactoriesLoaderFactoryClass () method returns the directly EnableAutoConfiguration class.
protectedClass<? > getSpringFactoriesLoaderFactoryClass() {return EnableAutoConfiguration.class;
}
Copy the code
So getCandidateConfigurations () method can filter out the key for org. Springframework. Boot. Autoconfigure. EnableAutoConfiguration the fully qualified name of the corresponding values.
The SpringFactoriesLoader is used to query all implementation classes specified in the meta-INF/Spring. factories properties configuration
2 Spring. factories file
The SpringFactoriesLoader class loads the Spring. factories file,
It will judge whether to load according to @conditionalonclass and other conditions in the AutoConfiguration file
The SpringFactoriesLoader loads meta-INF/Spring. factories files in all JAR files in the classpath. The code to load the spring.factories file is in the loadFactoryNames () method.
4 summarizes
Automatic configuration in Spring Boot simplifies configuration and makes using the Spring framework more flexible and convenient. It is also useful to use annotations to control whether a class is registered in a container. In the actual use, can realize the author’s greatness more.