This is my 13th day of the August Challenge

This series is the rearrangement of the previous series. With the development of the project and the use of the project, many things in the previous series have changed, and there are some things that were not mentioned in the previous series, so restart the series to rearrange, welcome to leave messages and exchange, thank you! ~

Our implementation of the Spring Cloud microservices framework uses many Of the Spring Cloud components and personalizes some of them. So how do we go about understanding the mechanics of a Spring Cloud component in general? And how do you know what the extension points are? Generally from the following two aspects:

  1. View the extension points of modules through the spring-boot SPI mechanism
  2. Look at the NamedContextFactory implemented by this module

The Spring-core project provides a variety of SPRING framework SPI mechanisms. One of the most common and flexible spring-boot mechanisms is the spring.factories based SPI mechanism.

So what is SPI (Service Provider)? In system design, in order to cooperate between modules, a unified interface is often designed for invocation between modules. In object-oriented design, it is generally recommended that modules be programmed based on interfaces, and that the implementation classes be not hardcoded between modules, but that the specific implementation be specified outside of the program. The default SPI mechanism in Java is implemented through ServiceLoader. In simple terms, create a file in the meta-INF /services directory called the fully qualified name of the interface, which contains the fully qualified name of the interface implementation class.

// Specify the interface class to load, and the class loader to use to load the class. <SpiService> ServiceLoader = Serviceloader.load (SpiService. Class, someClassLoader); Iterator<SpiService> iterator = serviceLoader.iterator(); while (iterator.hasNext()){ SpiService spiService = iterator.next(); }Copy the code

Gets the specified implementation class.

In the Spring framework, this class is SpringFactoriesLoader. You need to specify the interface and the corresponding implementation class in the meta-INF /spring.factories file, such as in Spring Cloud Commons:

# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.cloud.client.HostInfoEnvironmentPostProcessor
Copy the code

The realization of which specifies the EnvironmentPostProcessor HostInfoEnvironmentPostProcessor.

. At the same time, the Spring in the Boot will pass SpringFactoriesLoader loadXXX similar method reads all EnvironmentPostProcessor implementation class and generate the Bean into the ApplicationContext:

EnvironmentPostProcessorApplicationListener

// This class is loaded by specifying the implementation of ApplicationListener in spring.factories. Here to omit the public class EnvironmentPostProcessorApplicationListener implements SmartApplicationListener, Ordered {// when the Bean is created, Invokes the public EnvironmentPostProcessorApplicationListener () {this (EnvironmentPostProcessorsFactory .fromSpringFactories(EnvironmentPostProcessorApplicationListener.class.getClassLoader())); }}Copy the code

EnvironmentPostProcessorsFactory

static EnvironmentPostProcessorsFactory fromSpringFactories(ClassLoader classLoader) { return new ReflectionEnvironmentPostProcessorsFactory (. / / by SpringFactoriesLoader loadFactoryNames access file specifies the implementation class and initializes SpringFactoriesLoader.loadFactoryNames(EnvironmentPostProcessor.class, classLoader)); }Copy the code

The meta-INF /spring.factories file does not necessarily specify the interface and the corresponding implementation class, for example:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration,\
Copy the code

Where EnableAutoConfiguration is an annotation, LoadBalancerAutoConfiguration and BlockingLoadBalancerClientAutoConfiguration are configuration class is not EnableAutoConfiguration implementation. So what does this mean? EnableAutoConfiguration is an annotation, LoadBalancerAutoConfiguration and BlockingLoadBalancerClientAutoConfiguration are configuration class. Another special use of spring.factories here is to record which Bean classes are being loaded. EnableAutoConfiguration These beans are loaded when annotations are used. This is another use of spring.factories.

EnableAutoConfiguration is the core annotation for spring-Boot auto-loading. With this annotation, Spring-boot can automatically load various @Configuration annotated classes. So how does this work?

Look at the source EnableAutoConfiguration EnableAutoConfiguration

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; // Excluded Class<? >[] exclude() default {}; String[] excludeName() default {}; String[] excludeName() default {}; }Copy the code

So we see the @Import annotation. This annotation is a very common annotation in the Spring framework and is a major part of Spring’s Java-based annotation configuration.

  1. Check the meta-INF /spring.factories of the JAR package
  2. Check the content inside, especially focus on org. Springframework. Boot. Autoconfigure. EnableAutoConfiguration = automatic loading configuration class
  3. Look at the auto-loaded configuration classes to see which beans can be extended (for example, beans that contain the @ConditionalonMissingBean annotation)

We generally expect customization to be done with different Bean configurations that invoke different microservices, so the important thing to focus on is the NamedContextFactory extension of this module:

  1. Look for a class that extends the NamedContextFactory for this component
  2. Look at the source code of the class to see what the default configuration is, what the Specification class is, and how to get the name of the current microservice.
  3. Based on the default configuration class, see which beans are in it and which can be replaced (for example, beans with @ConditionalonMissingBean annotation)
  4. View the extended configuration mode according to Specification

Let’s take a simple example of spring-cloud-loadbalancer:

Spring – the cloud – expanded the loadbalancer NamedContextFactory classes are LoadBalancerClientFactory, inspect LoadBalancerClientFactory code can know:

  1. Can be achieved byloadbalancer.client.nameThis property gets which microservice the Bean is currently being created for
  2. You can know the default configuration isLoadBalancerClientConfigurationIf we look at the source code inside it, we can see that two main beans are initialized:
    1. ReactorLoadBalancer, because there is@ConditionalOnMissingBeanSo it can be replaced, so that’s our extension point
    2. ServiceInstanceSupplier: Supplier that provides instance information@ConditionalOnMissingBeanSo it can be replaced, so that’s our extension point
  3. Specification for LoadBalancerSpecification, and then analyze its calls can be know, can get through it@LoadBalancerClient@LoadBalancerClientsLoadBalancerClientConfigurationTo specify additional configurations.

This section examines in detail how to use and modify a Spring Cloud component. In the next section, we’ll begin to look at each of the features of the microservices framework we implemented.

Wechat search “my programming cat” to follow the public account, every day, easy to improve technology, win a variety of offers: