Why I went to understand some underlying annotations before, in fact, is to better understand the underlying principles of SpringBoot, such as the principle of automatic configuration.

A, @ SpringBootApplication

Start with @SpringBootApplication in MainApplication.

If you go to @SpringBootApplication, you can see that this is a composite annotation (highlighted in the red box).

1. @SpringBootConfiguration

What’s this note for?

If you click on the @Configuration annotation, it’s a Configuration class.

MainApplication is also a configuration class.

2. @ComponentScan

This is already familiar, specifying which Spring annotations to scan.

It’s just that there are some other filters that I’m not going to pay attention to.

3. @EnableAutoConfiguration

This is the most important annotation, sounds unusual name, turn on automatic configuration.

Click on it and it will also be a composite annotation (the red box needs attention).

(1) @ AutoConfigurationPackage

Sounds like an autoconfiguration package? Still click in.

The Registrar component is imported. Click on the Registrar component further.

The Registrar() application is to import a number of components into the container, namely the bulk Registrar component.

Make a breakpoint here and debug will start.

RegisterBeanDefinitions () has a passing parameter:

  • metadataIs the meta information of the annotation, and you can see that the annotation is annotated in thecom.pingguo.boot.MainApplication.

In the registerBeanDefinitions () method, a new a AutoConfigurationPackages PackageImports (), the inside of the incoming is yuan notes, through getPackageNames () to get to the package name.

AutoConfigurationPackages.register(
    registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0])
);
Copy the code

Under the idea can be executed independently in fragments of code (new AutoConfigurationPackages. PackageImports (metadata). GetPackageNames ().

Select and right – click, then Evaluate.

The result is com.pingguo.boot. Why this one? Because the annotations are in the MainApplication class, which belongs to com.pingguo.boot.

Once you get the package name, encapsulate it into an array (toArray(New String[0]) in the code snippet above) and register it.

The Registrar() application is to bulk register all the components under the specified package into the container.

(2) @ Import (AutoConfigurationImportSelector. Class)

Specified above good after the rules of the default package, we need to import the package, use AutoConfigurationImportSelector, continue to point in watching.

There’s a selectImports method that determines exactly what to import and returns an array.

Method in vivo, and call the getAutoConfigurationEntry () method to get the configuration entry, and then through getConfigurations () method to obtain the specific configuration, eventually to return an array.

Apparently getAutoConfigurationEntry () is a key.

Turn down a bit, is getAutoConfigurationEntry () implementation, here a breakpoint breakpoint cancel (above).

The debug to run it, go down to getCandidateConfigurations ().

Here are all the candidate configurations, and you can see that there are 127 of them.

Why these 127? In fact, it is written in the configuration file that loads all the scenarios for the container when SpringBoot starts.

The location defined is here: \spring-boot-autoconfigure\2.3.4.RELEASE\ spring-boot-autoconfigure-2.3.4.release.jar! \META-INF\spring.factories

Although all of these are loaded into the container at startup, the configuration is eventually turned on on demand.

For example, if you click on AOP and see @conditionalonClass ({advice.class}), the component will be imported only if the Advice class exists, but there is no Advice.

This is springboot-based Conditional assembly @Conditionality, which ultimately implements on-demand assembly according to the rules.

Examples of automatic configuration

Further understanding is illustrated with autoconfigurations that ultimately did not take effect, and those that did.

1. The automatic configuration does not take effect

For example, the cache.

You can see that several conditional assemblies are added to the CacheAutoConfiguration.

(1) @ ConditionalOnClass ({CacheManager. Class})

Run CTRL +N in idea to search for CacheManager. If the CacheManager exists, the condition is met.

(2) @ ConditionalOnBean ({CacheAspectSupport. Class})

This condition requires the presence of CacheAspectSupport in the container.

Now to determine if this component exists, add the test code to the main method:

. . String[] beanNamesForType = run.getBeanNamesForType(CacheAspectSupport.class); System.out.println("== Number of CacheAspectSupport components ==" + beannamesForType.length); . .Copy the code

Run to see the output.

The number of discoveries equals zero, which means that there are no components of that type.

That is, @conditionAlonBean ({cacheAspectSupport.class}) is not conditional. therefore, the entire CacheAutoConfiguration class is not in effect.

2. Automatic configuration that takes effect

If you have written a Web demo before, the Web-related configuration is valid, find it.

There are a lot of suffix is * * AutoConfiguration configuration, see DispatcherServletAutoConfiguration directly.

  • @Configuration(proxyBeanMethods = false) : indicates a Configuration class.

  • @ ConditionalOnWebApplication (type = the SERVLET) : whether the conditions for a web application, and is a native SERVLET type (and because springboot2 webflux), satisfy the current conditions.

  • ConditionalOnClass({dispatcherservlet.class}) : ConditionalOnClass({dispatcherservlet.class})

There are two notes that I haven’t seen directly, so I don’t need to pay too much attention to them.

  • AutoConfigureOrder: Configuration priority order for this configuration class.
  • @autoConfigureAfter: indicates that the class is configured after xxServletWebServerFactoryAutoConfiguration.classThen configure the current class.

So, if all the conditions on the class are satisfied, we can go further to the class.

See also conditional on DispatcherServletConfiguration class:

  • @Conditional({DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition.class}):

It’s not that long, but it’s actually one of the classes above

  • @ConditionalOnClass({ServletRegistration.class}): This also exists.

  • @EnableConfigurationProperties({WebMvcProperties.class}):

It’s not a conditional assembly. It’s used to bind external configuration files. Click on it.

As you can see, it is bound to all properties in the configuration file whose prefix is Spring.mvc.

In addition, components can be automatically registered with the container.

Here we can try adding output to main:

String[] beanNamesForType1 = run.getBeanNamesForType(WebMvcProperties.class); System.out.println("== number of components of type WebMvcProperties ==" + beannamesForType1.length);Copy the code

Run it and sure enough there is one:

To this, explain DispatcherServletConfiguration this configuration is also effective.

Further down you see the method dispatcherServlet() annotated with @bean, which registers the component of the dispatcherServlet type in the container.

Here’s what happened:

  • The new oneDispatcherServlet()objectdispatcherServlet.
  • And then todispatcherServletA set setting.
  • Finally, this object is returneddispatcherServlet.

Before learning about springMVC, you had to manually set up a bunch of stuff about DispatcherServlet. In SpringBoot it’s already set up at the bottom and registered to the container, so we can use it directly.

Third, summary

With further follow the source code to understand the principle of automatic configuration, so that their own deeper understanding of the advantages of SpringBoot.

There are so many things that we don’t need to configure manually, not that we don’t need them, but springBoot has already configured them for us at the bottom.

Of course, the current focus is still learning to use Springboot, but with the previous question to Learn SpringBoot, or more fruitful.