The people behind SpringBoot…

1. Background

​ In the past two years, with the prevalence of [microservices] , the SpringBoot framework has naturally been highly exposed. As programmers, if we don’t know something related to SpringBoot, it seems that we will be deeply despised when we go out to find a job. Before starting the SpringBoot journey, let’s review and explore the essence of the Spring framework, and then a little bit of a natural transition to SpringBoot, which is also very helpful for us to deeply understand SpringBoot.

Second, the origin of the Spring [framework]

​ In the “dark” EJB1 era, developers were very happy. At this time, the high-performance Spring framework to liberate developers came out. It was an era dominated by J2EE specifications. Software solutions based on various containers and J2EE specifications were the only “right way”. The bloated ecology and heavy development model made every development at that time painful. At this time, the technical giant Rod Johnson described the development concept of lightweight framework in his classic masterpiece “Expert One-on-One J2EE Design and Development”, attacked the original cumbersome specification, and then based on this book The research and development concept in China developed the initial version of the Spring framework, and then it became a mess. It has continued to this day, and it has not declined for more than 10 years.

The Spring framework is one of the best practices for building a high-performance Java R&D system. Through a series of concise and unified designs, it has opened a bright road for the majority of Java developers.

​ Spring has reasonably encapsulated and designed the technologies commonly used in Java development, including the well-known Spring IoC and AOP, etc., which can allow Java developers to avoid errors caused by inappropriate API and system design in the past, and also efficiently Complete the development work in the corresponding problem area with high quality, which is an essential artifact for Java development~

3. I didn’t expect Spring IoC to be so simple

​ I believe that many Java developers are stupidly confused about the concepts of IoC (Inversion Of Control) and DI (Dependency Injection), thinking that the two are the same thing. In fact, they are contained and contained relationships. There are two ways of IoC: DI and DL (Dependency Lookup), DI is the current software entity passively accepts other components it depends on to be injected by the IoC container, and DL is the current entity active Go to a service registry to find the components it depends on. The relationship between concepts is as follows:

​ The Spring IoC we often talk about actually refers to the IoC container implementation (IoC Container) provided by the Spring framework. Let’s look at a classic case used by a Spring IoC container:

public class Demo {
    public static void main(String[] args) {
        ApplicationContext context = new FileSystemXmlApplicationContext("config-file-path")
        DemoService service = context.getBean(DemoService.class);
        service.doSomething();
    }
}

I believe that every independent Java application built using the Spring framework usually has similar context.getBean(...)code. In fact, what this line of code does is DL, and what happens behind the construction of each IoC container is more of a DI process. , there may also be some DL logic used to interface with the old legacy system.

The dependency injection work of Spring’s IoC container is divided into two steps:

Stage 1. Collect and register beans

In this stage, developers define beans by way of XML or Java code, and then collect these defined beans into the IoC container in the form of manual assembly or automatic scanning by the container based on a specific mechanism.

If we collect and register the following single bean in XML configuration, the general form is as follows:

<bean id="DemoService" class="x.x.DemoService">
    ...
</bean>

As there are more and more beans in our project, it is more troublesome to manually configure one by one. We can also use the following configuration to scan and collect and register a batch of beans in batches:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"         
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 
         http://www.springframework.org/schema/context 
         http://www.springframework.org/schema/context/spring-context.xsd">
    // bean definition
</beans>

Stage 2. Analysis and Assembly

After the first stage is completed, we can temporarily think that the IoC container saves the beans that are independent of each other, and there is no relationship between them, but there is an indispensable relationship between them in the actual project, so what? , the second stage of the Ioc container is to analyze the beans already in the IoC container and assemble them in sequence according to their dependencies. The work turns out to be like this: IoC finds that a bean depends on another bean, then it will Inject another bean into the bean that depends on it, until all the bean’s dependencies are injected. At this time, all the beans in the container are ready to be used, which marks the completion of the work of the entire IoC container.

So what is the basis for IoC container analysis and assembly? In fact, in the earliest days, the Spring framework could only describe the relationship between beans and beans through XML configuration files. However, with the change of Java ecological research and development technology and concepts, a description method based on Java code and Annotation meta-information appeared (such as @@ AutoWired and @Inject). However, no matter which configuration method is used, the purpose is to simplify the various representations described by the binding logic, and ultimately serve the final purpose of this stage.

Fourth, what the hell is JavaConfig?

The birth of Java 5, coupled with the emergence of Guice, a dependency injection framework based on pure Java Annatation at that time, forced the Spring framework and the community to comply with public opinion, publishing and continuously improving the dependency binding description based on Java code and Annotation meta-information way, is the JavaConfig project.

The dependency description based on the JavaConfig method basically maps the configuration based on the early XML method, such as:

1. Form of expression

The XML configuration is as follows:

@Configuration 
public  class  DemoConfiguration  {
     // bean definition 
}

The configuration of JavaConfig is as follows:

<bean id="demoService" class="x.x.DemoServiceImpl">
    ...
</bean>

That is to say, any @ConfigurationJava class marked with an annotation is a JavaConfig configuration class.

2. Register the bean definition

XML configuration:

@Configuration
public class DemoConfiguration {
    @Bean
    public DemoService demoService() {
        return new DemoServiceImpl();
    }
}

JavaConfig configuration method:

<bean id="aService" class="x.x.AServiceImpl">
<bean id="bService" class="x.x.BServiceImpl">
    <property />
</bean>

That is to say, for any @Beanmethod marked with annotation, its return value will be registered in Spring’s IoC container as a bean definition, and the method name will default to the id of the bean in the container.

3. Expressing Dependency Injection Relationships

XML configuration form:

@Configuration
public class DemoConfiguration {
    @Bean
    public AService aService() {
        return new AServiceImpl();
    }
    @Bean
    public BService bService() {
        return new BServiceImpl(aService());
    }
}

JavaConfig form:

@Configuration
@PropertySource("classpath:1.properties")
@PropertySource("classpath:2.properties")
@PropertySource("...")
public class XConfiguration {
    ...
}

That is to say, if a bean is defined to depend on other beans, it can directly call the creation method of the dependent bean in its corresponding JavaConfig class.

From the above appearances, we can see that the features in the Spring IoC container in the past can be expressed in JavaConfig, but in another form. And by declaring the corresponding Java Annotation instead “cohesion” together, become more concise.

Five, those commonly used Annotation

  1. @ComponentScan

​ This annotation corresponds to the element in the XML configuration, which is <context:component-scan>used to cooperate with some meta-information Java Annotation, such as @Componentand @Repositoryetc., to collect the bean definition classes marked with these annotations into the Spring IoC container in batches.

​ We can fine-grainly customize the scope of automatic scanning of the annotation through attributes such as basePackage. If not specified, the default Spring framework will @ComponentScanscan from the package of the class where the annotation is declared.

​ What I want to talk about here @ComponentScanis an important component of the SpringBoot framework. We will encounter it in the future and will explain it in depth.

2. @PropertySourceand@PropertySources

​ The annotation @PropertySourceis used to load the configuration file from the specified place .properties, and load the properties in it into the IoC container, so that we can use it to fill in some bean-defined property placeholders (placeholder), of course, its implementation requires the cooperation of PropertySourcesPlaceHolderConfigurer .

If we use Java8 or higher, then we can declare multiple in parallel @PropertySource, such as:

@Configuration
@PropertySources({
    @PropertySource("classpath:1.properties"),
    @PropertySource("classpath:2.properties"),
    ...
})
public class XConfiguration {
    ...
}

If we use a JDK lower than Java8 to develop Spring applications, we must use @PropertySourcesannotations to implement multiple declarations @PropertySource, as follows:

@Configuration
@Import(DemoConfiguration.class)
public class XConfiguration {
    ...
}

3. @Importand@ImportSource

In the previous XML configuration method, we can <import resource="xxx.xml"/>combine multiple separate container configurations into one configuration by passing. In the configuration in the form of JavaConfig, we can use @Importthis annotation to achieve the same purpose:

@Configuration
@Import
@ImportSource(...)
public class XConfiguration {
    ...
}

Annotations @Importcan only introduce configurations defined in the form of JavaConfig into the IoC container, and if we have some legacy configurations or legacy systems that need to be configured in XML (such as the Dubbo framework), we need to use @ImportSourceannotations to merge them together into a container configured as a JavaConfig configuration:

@Configuration
@Import
@ImportSource(...)
public class XConfiguration {
    ...
}

6. Summary

Through this article, we reviewed the Spring framework and the conceptual analysis of IoC, and also learned the cornerstone of SpringBoot’s implementation: JavaConfig. Then it also introduces some of the most commonly used annotations in SpringBoot. It has laid a good foundation for us to learn and quickly get started with SpringBoot in the future. Come on, bobs…

I have a WeChat public account, and I often share some dry goods related to Java technology; if you like my sharing, you can use WeChat to search for “Java Head” or “javatuanzhang” to follow.

Leave a Comment

Your email address will not be published. Required fields are marked *