A few days ago we learned how to create a project springboot Today we talk about how he runs Why we do not need to go write heavy profiles
@SpringBootApplication
First we look at this comment, he is used to mark the main program, that he is a springboot project
@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 the click-through @SpringBootApplication comment we focus on the last three notes
@ComponentScan (Pack scan)
-
component is a component, scan scan, so the meaning of this annotation is used to scan component,
-
All components need to inject componentScan is to scan the marked classes reside under the package, which is injected, where he is reflected in @SpringBootApplication in, so this comment is automatically injected into the main program where all the components in the package
-
Previously ssm project we need to configure our packages scan
<context:component-scan base-package="com.xxx"></context:component-scan>
@EnableAutoConfiguration (automatic assembly Open)
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({AutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
Here we focus on two notes
一、@AutoConfigurationPackage
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import({Registrar.class}) public @interface AutoConfigurationPackage { }
In this annotation, primarily to obtain components under our own package to comment register
static class Registrar the implements ImportBeanDefinitionRegistrar, DeterminableImports { Registrar () { } // Metadata annotation is located meta information of our public void registerBeanDefinitions (AnnotationMetadata Metadata, the BeanDefinitionRegistry Registry) { // see where all the components of our own package to be annotated Register AutoConfigurationPackages.register (Registry, ( new new AutoConfigurationPackages.PackageImport (Metadata)) getPackageName ().); } public the Set <Object> determineImports (AnnotationMetadata Metadata) { return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata)); } }
register method: AutoConfigurationPackages registered by the component to the package
Private static Final String BEAN = AutoConfigurationPackages. class .getName (); public static void Register (the BeanDefinitionRegistry Registry, packagenames String ...) { // first determine the whole has not been registered BEAN IF (registry.containsBeanDefinition (BEAN)) { // Get the bean define the BeanDefinition BeanDefinition = registry.getBeanDefinition (bEAN); // Get the value of the parameter by the constructor bean ConstructorArgumentValues constructor Arguments = beanDefinition.getConstructorArgumentValues (); // add the parameter values, constructorArguments.addIndexedArgumentValue (0 , addBasePackages (Constructor Arguments, packagenames)); } the else { // create a new definition of the bean GenericBeanDefinition BeanDefinition = new new GenericBeanDefinition (); // set the type of the bean is AutoConfigurationPackages type beanDefinition.setBeanClass (AutoConfigurationPackages.BasePackages . class ); beanDefinition.getConstructorArgumentValues () addIndexedArgumentValue (. 0 , packagenames); beanDefinition.setRole ( 2 ); // for registration bean registry.registerBeanDefinition(BEAN, beanDefinition); } }
二、@Import({AutoConfigurationImportSelector.class})
Our automatic assembly configuration into selector
We point into this class, there is a following method getAutoConfigurationEntry acquired automatic assembly inlet,
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } else { AnnotationAttributes attributes = this.getAttributes(annotationMetadata); List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes); configurations = this.removeDuplicates(configurations); Set<String> exclusions = this.getExclusions(annotationMetadata, attributes); this.checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = this.filter(configurations, autoConfigurationMetadata); this.fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions); } }
This way he mainly gained configurations of a collection at this point we go getCandidateConfigurations method
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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; }
We first see him this red error message: META-INF / spring.factories not found automatically configure class. According to his error message we can conclude that he is to get our automatic configuration information from the META-INF / spring.factories
We can also enter at this point loadFactoryNames this method
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); //调用了下面的方法loadSpringFactories return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList()); } private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) { MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader); if (result != null) { return Result; } the else { the try { // to obtain the configuration file information according to the class loader to the Enumeration <the URL> = URLs classLoader =! null ClassLoader.getResources ( "the META-INF / spring.factories"):? ClassLoader.getSystemResources ( "the META-INF / spring.factories" ); LinkedMultiValueMap Result = new new LinkedMultiValueMap (); the while (urls.hasMoreElements ()) { the URL URL = (the URL) urls.nextElement (); a UrlResource Resource = new newA UrlResource (URL); // configuration information becomes final conversion after many properties form the Properties properties = PropertiesLoaderUtils.loadProperties (Resource); the Iterator var6 = properties.entrySet () Iterator ();. // loop configuration information acquired all the while ( var6.hasNext ()) { the entry <? ?,> = entry (the entry) var6.next (); String factoryClassName = ((String). entry.getKey ()) TRIM (); String [] var9 = StringUtils.commaDelimitedListToStringArray ((String) entry.getValue ()) ;int var10 = var9.length; for(int var11 = 0; var11 < var10; ++var11) { String factoryName = var9[var11]; result.add(factoryClassName, factoryName.trim()); } } } cache.put(classLoader, result); return result; } catch (IOException var13) { throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13); } } }
And this configuration file where is it
Find our spring-boot-autoconfigure in our project External Libraries
This completes our default equipped with some automatic
@SpringBootConfiguration
This method is relatively simple, indicating that this is a configuration class
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration public @interface SpringBootConfiguration { }
There have been struggles, there have been failures, but will still get up and continue fighting