Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand the startup principle of SpringBoot through code examples

2025-03-30 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article is about how to understand the startup principle of SpringBoot through code examples, the editor thinks it is very practical, so I share it with you to learn. I hope you can get something after reading this article.

Compared with Spring, SpringBoot has many advantages, such as automatic configuration, direct operation of jar, and so on. So how exactly did SpringBoot start up?

Here is the entrance to the SpringBoot startup:

@ SpringBootApplicationpublic class HelloApplication {public static void main (String [] args) {SpringApplication.run (HelloApplication.class, args);}}

First, take a look at the @ SpringBoot annotation:

@ Target ({ElementType.TYPE}) / / defines the timing of its use @ Retention (RetentionPolicy.RUNTIME) / / the compiler stores the Annotation in a class file that can be read and used by VM code that uses the reflection mechanism. @ Documented / / this annotation should be recorded by the javadoc tool @ Inherited / / annotated classes will automatically inherit. More specifically, if you define the annotation with the @ Inherited tag, and then use the defined annotation to mark another parent class, and the parent class has a subclass (subclass), then all attributes of the parent class will be inherited into its subclass. @ SpringBootConfiguration / / @ SpringBootConfiguration is equivalent to @ Configuration. The JavaConfig configuration form @ EnableAutoConfiguration@ComponentScan (excludeFilters = {@ Filter (type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class}), @ Filter (type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class})} / / automatically scans and loads eligible components. Fine-grained customization of the scope of @ ComponentScan automatic scanning through attributes such as basePackages, if not specified, the default Spring framework implementation scans from the package that declares the class of @ ComponentScan. Note: therefore, the startup class of SpringBoot is best placed under root package, because basePackages is not specified by default.) Public @ interface SpringBootApplication {@ AliasFor (annotation = EnableAutoConfiguration.class) Class [] exclude () default {}; @ AliasFor (annotation = EnableAutoConfiguration.class) String [] excludeName () default {}; @ AliasFor (annotation = ComponentScan.class, attribute = "basePackages") String [] scanBasePackages () default {}; @ AliasFor (annotation = ComponentScan.class, attribute = "basePackageClasses") Class [] scanBasePackageClasses () default {};}

So, in fact, SpringBootApplication annotations are equivalent to a combination of three annotations, @ SpringBootConfiguration,@ComponentScan and @ EnableAutoConfiguration.

@ SpringBootConfiguration and @ ComponentScan, it's easy to know what it means, one is the JavaConfig configuration, the other is the scan package. The key is the @ EnableAutoConfiguration annotation. Let's take a look at this note first:

@ 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 {};}

When ConfigurationClassParser is used to analyze the configuration class during the startup of the Springboot application, if @ Import (ImportSelector) is found in the annotation, a corresponding ImportSelector object is created and its method public String [] selectImports (AnnotationMetadata annotationMetadata) is called. This is the case with the import of EnableAutoConfigurationImportSelector @ Import (EnableAutoConfigurationImportSelector.class), so ConfigurationClassParser instantiates an EnableAutoConfigurationImportSelector and calls its selectImports () method.

AutoConfigurationImportSelector implements DeferredImportSelector extends ImportSelector .

The following is the execution process of AutoConfigurationImportSelector:

Public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {private static final String [] NO_IMPORTS = new String [0]; private static final Log logger = LogFactory.getLog (AutoConfigurationImportSelector.class); private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude"; private ConfigurableListableBeanFactory beanFactory; private Environment environment; private ClassLoader beanClassLoader; private ResourceLoader resourceLoader; public AutoConfigurationImportSelector () {} public String [] selectImports (AnnotationMetadata annotationMetadata) {if (! this.isEnabled (annotationMetadata)) {return NO_IMPORTS } else {/ / load AutoConfigurationMetadata AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata (this.beanClassLoader); AnnotationAttributes attributes = this.getAttributes (annotationMetadata) from the configuration file; / / get all candidate configuration classes EnableAutoConfiguration / / use internal tools to use SpringFactoriesLoader, look for / / META-INF\ spring.factories in all jar packages on classpath, and find the factory class name where key is defined as / / org.springframework.boot.autoconfigure.EnableAutoConfiguration / /. / / although the parameter has annotationMetadata,attributes, in the / / implementation getCandidateConfigurations () of AutoConfigurationImportSelector, these two parameters do not use List configurations = this.getCandidateConfigurations (annotationMetadata,attributes); / / deduplicated configurations = this.removeDuplicates (configurations); Set exclusions = this.getExclusions (annotationMetadata,attributes); / / apply exclusion attribute this.checkExcludedClasses (configurations, exclusions); configurations.removeAll (exclusions) / / apply filter AutoConfigurationImportFilter, / / for spring boot autoconfigure, define a filter that needs to be applied: / / org.springframework.boot.autoconfigure.condition.OnClassCondition, / / this filter checks the annotation @ ConditionalOnClass on the candidate configuration class. If the required class does not exist in classpath / /, the candidate configuration class will be excluded from configurations = this.filter (configurations, autoConfigurationMetadata). / / all candidate configuration classes that need to be applied have been found / / broadcast event AutoConfigurationImportEvent this.fireAutoConfigurationImportEvents (configurations, exclusions); return StringUtils.toStringArray (configurations);}} protected AnnotationAttributes getAttributes (AnnotationMetadata metadata) {String name = this.getAnnotationClass (). GetName (); AnnotationAttributes attributes = AnnotationAttributes.fromMap (metadata.getAnnotationAttributes (name, true)); Assert.notNull (attributes, ()-> {return "No auto-configuration attributes found. Is "+ metadata.getClassName () +" annotated with "+ ClassUtils.getShortName (name) +";}); return attributes;} protected List getCandidateConfigurations (AnnotationMetadata metadata, AnnotationAttributes attributes) {List 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;} public abstract class SpringFactoriesLoader {public static final String FACTORIES_RESOURCE_LOCATION =" META-INF/spring.factories "; private static final Log logger = LogFactory.getLog (SpringFactoriesLoader.class); private static final Map cache = new ConcurrentReferenceHashMap (); public SpringFactoriesLoader () {} public static List loadFactoryNames (Class factoryClass, @ Nullable ClassLoader classLoader) {String factoryClassName = factoryClass.getName (); return (List) loadSpringFactories (classLoader) .getOrDefault (factoryClassName, Collections.emptyList ()) }} private List filter (List configurations, AutoConfigurationMetadata autoConfigurationMetadata) {long startTime = System.nanoTime (); String [] candidates = StringUtils.toStringArray (configurations); / / record whether candidate configuration classes need to be excluded. If skip is true, it means that candidates need to be excluded, initialized to false, and do not need to be excluded. Boolean [] skip = new boolean [candidates.length]; / / record whether any candidate configuration classes are ignored, initialize as false boolean skipped = false Iterator var8 = this.getAutoConfigurationImportFilters (). Iterator (); / get AutoConfigurationImportFilter and filter while (var8.hasNext ()) {AutoConfigurationImportFilter filter = (AutoConfigurationImportFilter) var8.next () one by one; / / a pair of filters inject information this.invokeAwareMethods (filter) that it needs Aware; / / use this filter to check the match between candidate configuration classes and autoConfigurationMetadata [] match = filter.match (candidates, autoConfigurationMetadata); for (int I = 0; I < match.length) + + I) {if (! match [I]) {/ / if a candidate configuration class does not meet the current filter, mark it as needs to be excluded, / / and set skipped to true, indicating that a candidate configuration class needs to be excluded skip [I] = true; skipped = true } if (! skipped) {/ / if all candidate configuration classes do not need to be excluded, directly return the set of candidate configuration classes provided by the external parameter return configurations } else {/ / Logic goes here because skipped is true, indicating that some candidate configuration classes / / need to be excluded in the above filter application logic. Here, the candidate configuration classes that need to be excluded are excluded and / / a new collection of candidate configuration classes that do not need to be excluded is returned to the caller List result = new ArrayList (candidates.length); int numberFiltered; for (numberFiltered = 0; numberFiltered < configuration) + + numberFiltered) {if (! skip [numberFiltered]) {result.add (candidates [numberfiltered]);}} if (logger.isTraceEnabled ()) {numberFiltered = configurations.size ()-result.size (); logger.trace ("Filtered" + numberFiltered + "auto configuration class in" + TimeUnit.NANOSECONDS.toMillis (System.nanoTime ()-startTime) + "ms");} return new ArrayList (result) }} / * use the internal tool SpringFactoriesLoader to find the * META-INF\ spring.factories in all jar packages on classpath, find out the filter class defined by the key attribute of * org.springframework.boot.autoconfigure.AutoConfigurationImportFilter *, and instantiate it. * AutoConfigurationImportFilter filters can be registered with spring.factories to impose some restrictions on autoconfiguration classes * to quickly exclude the bytecodes of these autoconfiguration classes before they are read. * spring boot autoconfigure registers an AutoConfigurationImportFilter by default: * org.springframework.boot.autoconfigure.condition.OnClassCondition * * / protected List getAutoConfigurationImportFilters () {return SpringFactoriesLoader.loadFactories (AutoConfigurationImportFilter.class, this.beanClassLoader);}

2. Let's take a look at the execution process of the run method when SpringBoot starts

Public ConfigurableApplicationContext run (String... Args) {StopWatch stopWatch = new StopWatch (); stopWatch.start (); ConfigurableApplicationContext context = null; Collection exceptionReporters = new ArrayList (); this.configureHeadlessProperty (); / / get SpringApplicationRunListeners listeners = getRunListeners (args) from META-INF/spring.factories under the classpath; / / call back all get SpringApplicationRunListener.starting () methods listeners.starting (); try {/ / encapsulate the command line parameter ApplicationArguments applicationArguments = new DefaultApplicationArguments (args); / / prepare the environment ConfigurableEnvironment environment = prepareEnvironment (listeners, applicationArguments) / / callback SpringApplicationRunListener.environmentPrepared () after the environment is created Indicates that the environment is ready to complete the this.configureIgnoreBeanInfo (environment); / / print the Banner diagram Banner printedBanner = printBanner (environment); / / create the ApplicationContext and decide whether to create the ioc of the web or the normal ioc context = createApplicationContext (); / / exception analysis report exceptionReporters = getSpringFactoriesInstances (SpringBootExceptionReporter.class, new Class [] {ConfigurableApplicationContext.class}, context) / / prepare the context, save the environment to ioc / / applyInitializers (): call back all the ApplicationContextInitializer initialize methods / / listeners.contextPrepared (context) / / prepareContext saved before the callback is completed, call back all SpringApplicationRunListener's contextLoaded () this.prepareContext (context, environment, listeners, applicationArguments, printedBanner) / / refresh container, ioc container initialization (embedded Tomcat will also be created if it is a web application) / / scan, create, load all components, (configuration class, component, auto configuration) this.refreshContext (context); this.afterRefresh (context, applicationArguments); stopWatch.stop (); if (this.logStartupInfo) {new StartupInfoLogger (this.mainApplicationClass) .logStarted (getApplicationLog (), stopWatch);} / all SpringApplicationRunListener callback started methods listeners.started (context) / / get all ApplicationRunner and CommandLineRunner from the ioc container for callback, / / ApplicationRunner callback first, then CommandLineRunner callback this.callRunners (context, applicationArguments);} catch (Throwable ex) {this.handleRunFailure (context, ex, exceptionReporters, listeners); throw new IllegalStateException (ex);} try {/ / all SpringApplicationRunListener callback running methods listeners.running (context);} catch (Throwable ex) {this.handleRunFailure (context, ex, exceptionReporters, null); throw new IllegalStateException (ex) } / / return the launched ioc container return context;} after the entire SpringBoot application is launched

The above is how to understand the SpringBoot startup principle through code examples. The editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report