Start the class
Call the SpringApplication.run method to start the class using the @SpringBootApplication annotation
@SpringBootApplication public class StringBootDemoApplication { public static void main(String[] args) { SpringApplication.run(StringBootDemoApplication.class, args); }}Copy the code
@ SpringBootApplication annotations
@target (elementType.type) // Scope of annotations, where TYPE is used to describe classes, interfaces (including package annotation types), or enum statements @Retention(retentionPolicy.runtime) // Lifecycle of annotations, Documented // Indicates that this annotation should be Documented by Javadoc. @inherited // Subclasses inherit this annotation. @springBootConfiguration // @enableAutoConfiguration // Enable springBoot annotation function, one of the four magic tools of SpringBoot, @componentScan (excludeFilters = {// Filter path set @filter (type = filterType.custom, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { ... }Copy the code
@ Configuration annotations
Instead of using XML Configuration files in springMVC, we mostly use Configuration classes to solve Configuration problems in SpringBoot. Beans that can be loaded by @Configuration annotations:
1. Configure beans in the form of an XML configuration file
<? The XML version = "1.0" encoding = "utf-8"? > <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd "default - lazy - init =" true "> <! -- Bean definition --> </beans>Copy the code
2. Java Configuration configures beans
@configuration public class MockConfiguration{//bean definition}Copy the code
The return value of any method labeled @bean is registered with Spring’s IoC container as a Bean definition, and the method name defaults to the id of the Bean definition.
@ ComponentScan annotations
ComponentScan automatically scans and loads qualified components (@Component, @repository, etc.) or bean definitions in XML files labeled with < Context: Component-scan > tags. Loading these bean definitions into the IoC container allows fine-grained customization of the scope that @ComponentScan automatically scans through properties such as basePackages. If not specified, the default Spring framework implementation scans from the package of the class in which @ComponentScan is declared. So it is best to place the SpringBoot boot class under the root package, since basePackages are not specified by default
/** * Configures component scanning directives for use with @{@link Configuration} classes. * Provides support parallel with Spring XML's {@code <context:component-scan>} element. * * <p>Either {@link #basePackageClasses} or {@link #basePackages} (or its alias * {@link #value}) may be specified to define specific packages to scan. If specific * packages are not defined, scanning will occur from the package of the * class that declares this annotation. * * <p>Note that the {@code <context:component-scan>} element has an * {@code annotation-config} attribute; however, this annotation does not. This is because * in almost all cases when using {@code @ComponentScan}, default annotation config * processing (e.g. processing {@code @Autowired} and friends) is assumed. Furthermore, * when using {@link AnnotationConfigApplicationContext}, annotation config processors are * always registered, meaning that any attempt to disable them at the * {@code @ComponentScan} level would be ignored. @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Repeatable(ComponentScans.class) public @interface ComponentScan { @AliasFor("basePackages") String[] value() default {}; @AliasFor("value") String[] basePackages() default {}; Class<? >[] basePackageClasses() default {}; Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class; Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class; ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT; String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN; boolean useDefaultFilters() default true; Filter[] includeFilters() default {}; Filter[] excludeFilters() default {}; boolean lazyInit() default false; @Retention(RetentionPolicy.RUNTIME) @Target({}) @interface Filter { FilterType type() default FilterType.ANNOTATION; @AliasFor("classes") Class<? >[] value() default {}; @AliasFor("value") Class<? >[] classes() default {}; String[] pattern() default {}; }}Copy the code
@EnableAutoConfiguration
This annotation is, as its name implies, automatically configurable, so it is probably the most important annotation in SpringBoot. This annotation is described in more detail in the comment information: Auto-load Beans
In the Spring framework, annotations starting with @enable are provided, such as @enablescheduling, @Enablecaching, and @enablembeanexport. The @enableAutoConfiguration concept and way of doing things is the same: collect and register scenario-specific bean definitions with the support of @import.
- @enablescheduling is an IoC container loaded with Spring scheduling framework related bean definitions via @import.
- @enablembeanExport loads jMX-related bean definitions into the IoC container via @import
- @enableAutoConfiguration also loads into the IoC container all bean definitions that qualify for automatic configuration with the help of @import.
As a composite Annotation, @enableAutoConfiguration defines the key information as follows:
/** * Enable auto-configuration of the Spring Application Context, attempting to guess and * configure beans that you are likely to need. Auto-configuration classes are usually * applied based on your classpath and what beans you have defined. For example, if you * have {@code tomcat-embedded.jar} on your classpath you are likely to want a * {@link TomcatServletWebServerFactory} (unless you have defined your own * {@link ServletWebServerFactory} bean). * <p> * When using {@link SpringBootApplication @SpringBootApplication}, the auto-configuration * of the context is automatically enabled and adding this annotation has therefore no * additional effect. * <p> * Auto-configuration tries to be as intelligent as possible and will back-away as you * define more of your own configuration. You can always manually {@link #exclude()} any * configuration that you never want to apply (use {@link #excludeName()} if you don't * have access to them). You can also exclude them via the * {@code spring.autoconfigure.exclude} property. Auto-configuration is always applied * after user-defined beans have been registered. * <p> * The package of the class that is annotated with {@code @EnableAutoConfiguration}, * usually via {@code @SpringBootApplication}, has specific significance and is often used * as a 'default'. For example, it will be used when scanning for {@code @Entity} classes. * It is generally recommended that you place {@code @EnableAutoConfiguration} (if you're * not using {@code @SpringBootApplication}) in a root package so that all sub-packages * and classes can be searched. * <p> * Auto-configuration classes are regular Spring {@link Configuration @Configuration} * beans. They are located using the {@link SpringFactoriesLoader} mechanism (keyed * against this class). Generally auto-configuration beans are * {@link Conditional @Conditional} beans (most often using * {@link ConditionalOnClass @ConditionalOnClass} and * {@link ConditionalOnMissingBean @ConditionalOnMissingBean} annotations). * * @author Phillip Webb * @author Stephane Nicoll * @since 1.0.0 * @see ConditionalOnBean * @see ConditionalOnMissingBean * @see ConditionalOnClass * @see AutoConfigureAfter * @see SpringBootApplication */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { /** * Environment property that can be used to override when auto-configuration is * enabled. */ String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; /** * Exclude specific auto-configuration classes such that they will never be applied. * @return the classes to exclude */ Class<? >[] exclude() default {}; /** * Exclude specific auto-configuration class names such that they will never be * applied. * @return the class names To exclude * @since 1.3.0 */ String[] excludeName() default {}; }Copy the code
There are also two comments on this note:
- @AutoConfigurationPackage
- @Import(AutoConfigurationImportSelector.class)
@ AutoConfigurationPackage and @ Import (AutoConfigurationImportSelector. Class) using the @ Import annotations
@AutoConfigurationPackage
The source code:
/** * Registers packages with {@link AutoConfigurationPackages}. When no {@link #basePackages * base packages} or {@link #basePackageClasses base package classes} are specified, The * package of the annotated class is registered. * * @author Phillip Webb * @since 1.3.0 * @see AutoConfigurationPackages */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage { /** * Base packages that should be registered with {@link AutoConfigurationPackages}. * <p> * Use {@link #basePackageClasses} for a type-safe Alternative to string-based package * names. * @return the back package names * @since 2.3.0 */ String[] basePackages() default {}; /** * Type-safe alternative to {@link #basePackages} for specifying the packages to be * registered with {@link AutoConfigurationPackages}. * <p> * Consider creating a special no-op marker class or interface in each package that * Serves no purpose other than being referenced by this attribute. * @return the base package classes * @since 2.3.0 */ Class<? >[] basePackageClasses() default {}; }Copy the code
Through the annotated source code as you can see, this annotation and use the @ Import (AutoConfigurationPackages. The Registrar. Class) annotations, open AutoConfigurationPackages. The Registrar
/** * {@link ImportBeanDefinitionRegistrar} to store the base package from the importing * configuration. */ static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {/ / registered org. Springframework. Boot. The autoconfigure. AutoConfigurationPackages BeanDefinition Override public void registerBeanDefinitions(AnnotationMetadata) BeanDefinitionRegistry registry) { register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0])); } @Override public Set<Object> determineImports(AnnotationMetadata metadata) { return Collections.singleton(new PackageImports(metadata)); }}Copy the code
Import(AutoConfigurationImportSelector.class)
1) AutoConfigurationImportSelector AutoConfigurationImportSelector implements DeferredImportSelector from ImportSelector inherited methods: SelectImports.
@Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (! isEnabled(annotationMetadata)) { return NO_IMPORTS; } AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); }Copy the code
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) { if (! isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } AnnotationAttributes attributes = getAttributes(annotationMetadata); / / load components jar under the meta-inf/spring. Factories "" List < String > configurations = getCandidateConfigurations (annotationMetadata, attributes); configurations = removeDuplicates(configurations); Set<String> exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = getConfigurationClassFilter().filter(configurations); fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationEntry(configurations, exclusions); }Copy the code
Return the auto-configuration class names that should be considered The default load spring. Factories file down the org. Springframework. Boot. Autoconfigure. EnableAutoConfiguration = \ all the classes below, Meta-inf /spring.factories looks like this:
/** * Return the auto-configuration class names that should be considered. By default * this method will load candidates using {@link SpringFactoriesLoader} with * {@link #getSpringFactoriesLoaderFactoryClass()}. * @param metadata the source metadata * @param attributes the {@link #getAttributes(AnnotationMetadata) annotation * attributes} * @return a list of candidate configurations */ protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {// Is the default collection of all-class names to be selected for loading. 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
Configurations in your code is actually a collection of these full class names, and you can launch it in debug mode by putting a breakpoint there, and you can see that what’s in there is the same thing as what’s in the Spring.Factories
This method is executed before springBoot starts the process — bean instantiation, returning a list of classes to be instantiated;
In fact, in addition to the org. Springframework. Boot. Autoconfigure. EnableAutoConfiguration, spring. Factories also defines many other beans inside. All of these beans are loaded through the Spring factory loader, the SpringFactoriesLoader.
**2)Spring factory loader SpringFactoriesLoader
It’s more of a configuration lookup feature, According to the full name of the class of the @ EnableAutoConfiguration org. Springframework. Boot. Autoconfigure. EnableAutoConfiguration as a lookup Key, obtain corresponding to a set of @ Configura Tion class
To get the class to reload, use the following method:
public static List<String> loadFactoryNames(Class<? > factoryType, @Nullable ClassLoader classLoader) { ClassLoader classLoaderToUse = classLoader; if (classLoaderToUse == null) { classLoaderToUse = SpringFactoriesLoader.class.getClassLoader(); } String factoryTypeName = factoryType.getName(); // Its key is the name of our annotation class, such as "EnableAutoConfiguration", Return loadSpringFactories(classLoaderToUse).getorDefault (factoryTypeName, Collections.emptyList()); } returns information about spring.factories in the form of Map<String, List<String>>, Private static Map<String, List<String>> loadSpringFactories(ClassLoader ClassLoader) {Map<String, List<String>> result = cache.get(classLoader); if (result ! = null) { return result; } result = new HashMap<>(); try { Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION); while (urls.hasMoreElements()) { URL url = urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); for (Map.Entry<? ,? > entry : properties.entrySet()) { String factoryTypeName = ((String) entry.getKey()).trim(); String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String) entry.getValue()); for (String factoryImplementationName : factoryImplementationNames) { result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>()) .add(factoryImplementationName.trim()); } } } // Replace all lists with unmodifiable lists containing unique elements result.replaceAll((factoryType, implementations) -> implementations.stream().distinct() .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList))); cache.put(classLoader, result); } catch (IOException ex) { throw new IllegalArgumentException("Unable to load factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex); } return result; }Copy the code
If we get the class information, Spring can load the class into the JVM through the classloader. Now that we’ve relied on the components we need through spring-Boot’s starter dependency, the class information for those components can be retrieved in the Select method.
So the magic of @enableAutoConfiguration actually becomes:
Search all meta-INF/Spring. factories configuration files from the classpath, And will the org. Springframework. Boot. Autoconfigure. EnableAutoConfiguration corresponding configuration items through reflection (Java Refletion) instantiated into the corresponding IoC container Configuration class in JavaConfig form annotated with @Configuration, then aggregated into one and loaded into the IoC container.
【 reference article 】 【1】juejin.cn/post/689534… (2) www.cnblogs.com/theRhyme/p/…