"In-depth Practice of Spring Boot" Reading Notes No. 3: Analysis of Core Technology Source Code

Friends who have just followed, you can review the previous two articles:

The last article summarizes the second part of "In-depth Practice of Spring Boot", and this article summarizes the third and last part. This part mainly explains the source code analysis of the core technology. Due to the space and ability, the analysis will not be too detailed. After further research, I will write an article. I hope you can learn about the functions provided by Spring Boot from the three articles in "Reading Notes", practice in the project, and constantly free yourself from tedious and repetitive development.

I also just started to understand Spring Boot recently, and I plan to practice it in the project this year. I will summarize some problems and experiences in the practice process and share it with you. Friends who want to learn, practice and communicate together can scan the QR code below the article and follow my personal public account, thank you.

This paper mainly summarizes the following aspects:

  • Spring Boot automatic configuration implementation principle;
  • Spring Boot data access implementation principle;
  • Implementation principle of microservice core technology;

Off topic

The Spring Festival holiday is coming to an end soon, and I will go to work tomorrow. I believe that everyone is still unsatisfied, not enough to eat, not enough to play, not enough to spend with their families. This year, due to personal reasons, I did not go home for the Chinese New Year. The ones I care most about are my grandparents. They are all in their 80s. I hope they will be healthy and spend the last journey of their lives happily.

Anyway, everyone is going to switch channels, return to normal work, work hard, and look forward to a better reunion with your family next year.

Spring Boot automatic configuration implementation principle

Using Spring Boot to create a simple web project is very simple and does not require much configuration, just write a simple main program:

@SpringBootApplication
public class ConfigApplication{
    public static void main(String[] args) {
        SpringApplication.run(ConfigApplication.class, args);
}
Main program analysis

First analyze the run method (omit uncritical parts of the code):

public ConfigurableApplicationContext run(String... args) {

        ConfigurableApplicationContext context = null;
        configureHeadlessProperty();
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.started();
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
            ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
            Banner printedBanner = printBanner(environment);
            context = createApplicationContext();
            analyzers = new FailureAnalyzers(context);
            prepareContext(context, environment, listeners, applicationArguments,
                    printedBanner);
            listeners.finished(context, null);
            return context;
        }
        catch (Throwable ex) {
            handleRunFailure(context, listeners, analyzers, ex);
            throw new IllegalStateException(ex);
        }
    }

It first starts a SpringApplicationRunListeners listener, then creates an application context ConfigurableApplicationContext, and loads the classes and various environment configurations required by the application through this context.

For an application to run normally, it needs some environment variables, various resources and some related configurations, etc. Let's see that the createApplicationContext method will load the classes and various resources defined and required by the application.

Automatic configuration

All automatic configuration is introduced from the annotation @SpringBootApplication, which actually includes @Configuration, @EnableAutoConfiguration and @ComponentScan. Among them, @EnableAutoConfiguration enables automatic configuration and will import some automatically configured class definitions.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    Class<?>[] exclude() default {};
    String[] excludeName() default {};
    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {};
    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {};
}

EnableAutoConfiguration will eventually import a list of auto-configured classes. There are many auto-configuration classes in the list. Most of these configuration classes will be imported and will be in a standby state. When related packages are introduced into the project, related functions will be enabled.

For example, if the reference of Redis is configured in the maven configuration of the project, the default configuration item of Redis will be enabled. First, the configuration in the project will be read. The default value of the configuration will only be enabled if there is no relevant configuration in the project. The following code is the automatic configuration of Redis. Configuration, if not set in the configuration file, the following default settings will be used.

@ConfigurationProperties(
    prefix = "spring.redis"
)
public class RedisProperties {
    private int database = 0;
    private String host = "localhost";
    private String password;
    private int port = 6379;
    private int timeout;
    private RedisProperties.Pool pool;
    private RedisProperties.Sentinel sentinel;
    private RedisProperties.Cluster cluster;

    public RedisProperties() {
    }

Through automatic configuration, it is not necessary to repeatedly define the name of the configuration item, just overwrite the agreed configuration item. You can see what configuration items are available by looking at each Properties class.

Spring Boot data access implementation principle

To use a database, you must first establish a connection to the database server. For relational databases, Spring Boot generally uses JDBC to connect to data sources. Other types of databases use their own separate ways to establish connections.

Data source types and drivers

The JDBC connection data source must specify the data source type and database driver. There are four main data sources:

  • Use the java.sql.DriverManager class;
  • Use a subclass that implements the javax.sql.DataSource interface. The DataSource interface is implemented by the driver provider. There are mainly three types of implementation, basic implementation, connection pool implementation, and distributed transaction implementation;
  • DBCP connection pool, an open source connection pool implementation under the Apache Software Foundation, Tomcat's connection pool is implemented using this connection pool;
  • C3P0 connection pool;

Spring Boot uses org.apache.tomcat.jdbc.pool.DataSource by default, which implements the javax.sql.DataSource interface using the second method. The type of data source can be changed through configuration.

In addition, Spring Boot supports almost all existing databases by default.

Data access function implementation

After the connection with the database is established, some access operations can be performed on the database to realize the management function of the database. Data access operations generally include two aspects, namely entity modeling and persistence.

Both relational databases and NoSQL databases follow this design specification. Entity modeling is to map common Java objects and relationships into database table machine-related relationships. In Spring Boot, it is mainly implemented through annotations.

Relational databases use a set of JPA standards, which combine with Hibernate to achieve entity persistence. Subsequent database management designs follow the standard specification of JPA, providing the same API for accessing the database.

Implementation principle of microservice core technology

Spring Cloud is a set of cloud application development tools based on the further encapsulation of Netfix open source components, which can be used to develop various microservice applications.

Configure service implementation

As mentioned in the previous article, the online update function of configuration management uses an event bus, namely spring-cloud-bus, to publish state changes, and uses distributed messages to publish update events. Distributed messages finally use RabbitMQ to achieve message sending and receiving.

Let’s review the online update process again:

  • Update the configuration file of the Git repository;
  • Start the update request with the POST instruction;
  • The configuration management server reads the configuration file from the Git repository, distributes the configuration file to each client, and publishes an update message in RabbitMQ;
  • The client subscribes to RabbitMQ messages, and performs the update after receiving the message;

The message distribution in the configuration management server is realized by calling the spring-cloud-stream component from spring-cloud-bus, and spring-cloud-stream uses RabbitMQ to realize distributed message distribution. Not to mention the specific implementation, I have a good understanding of using RabbitMQ.

Service discovery and load balancing

The client performs registration by using a scheduled task, and the client updates the list of other online clients from the discovery server, which is also managed by a scheduled task.

When an application enables service discovery, Ribbon's load balancing service is enabled by default. Ribbon obtains online clients through discovery services, and establishes a load balancing management mechanism for clients with multiple instances.

Distributed message implementation

Using spirng-cloud-stream, you can use RabbitMQ's asynchronous messages very simply. The distributed message distribution in Spring Cloud's configuration management is also achieved by calling the spring-cloud-stream component.

The following describes the distributed message implementation with the implementation of message producers and consumers

Message producer:

@EnableBinding(Source.class)
@RestController 
@SpringBootApplication 
public class SenderApplication { 
    @Autowired 
    @Output(Source.OUTPUT) 
    private MessageChannel channel;

    @RequestMapping(method = RequestMethod.POST, path = "/send") 
    public void write (@RequestBody Map<String, Object> msg){
        channel.send(MessageBuilder.withPayload(msg).build());
    } 

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

Message consumer:

@EnableBinding(Sink.class)
@IntegrationComponentScan
@MessageEndpoint
@SpringBootApplication
public class ReceiverApplication {
    @ServiceActivator(inputChannel=Sink.INPUT)
    public void accept(Map<String, Object> msg){
        System.out.println(msg.get("msg").toString() + ":" + msg.get("name"));
    }

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

As can be seen from the above analysis, Spring Boot and some related components have tried their best to help us realize some functions that can be realized and done. Although using Spring Boot and its related components looks very simple, it can actually achieve extremely powerful functions, which is the magic of Spring Boot and its components.

love story

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324630453&siteId=291194637