SpringBoot detailed injection configuration

SpringBoot injection configuration (2)

Next, let's talk about some detailed things about SpringBoot injection configuration, which is also summarized by combining online and other video learning. Although there will be content from other places. Thank you for your reading in advance, and you can criticize and correct local problems.

1. Introduction

When we used to learn spring, we usually created an xml file. For example, when configuring a connection pool, we often create the following:

<!--to configure druid Connection pool>
<bean id = "dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    <property name="url" value= "${jdbc.url}" />
    <property name = "username" value="${jdbc.username}" />
    <property name = "password" value="${jdbc.password}" />

Of course, this method also creates a configuration file to write the password, url and username corresponding to the connection pool.

So how should we face this problem (configuring connection pool) in spring boot?

This is about to understand the history of the spring framework.

2. History of spring

The following is drawn from: Features and history of each version of Spring framework

The project path of spring1.X is as follows:

At that time, spring was still in the configuration of full xml format, which was really a headache for programmers to configure the environment.

The source code project structure path of spring2.X is as follows:

In spring 2.0, annotation support has been added. Although the spring package we added depends on the version that should be used is almost 5.0 +, the learning in many places in the early stage is only within the scope of 2.X. (however, understanding the configuration of both should be more detailed for future understanding of spring 3.0 and above.)

In spring 3. X, we began to add the configuration of Java classes, and its structure is similar to the 5.X we currently rely on.

After spring 3.0, spring's annotations have been very perfect. Therefore, in this version, spring recommends using full java configuration to replace the previous xml.

3. Infuse

3.1 spring annotation injection

spring annotation configuration mainly depends on java classes and some annotations. Of course, common annotations are as follows:

  • @Configuration: declare a class as a configuration class instead of an xml file
  • @Bean: declared on the method, add the return value of the method to the bean container instead of the label
  • @value: attribute injection
  • @PropertySource: Specifies the external properties file

1. Introducing druid connection pool dependency

<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid</artifactId>
	<version>1.1.10</version>
</dependency>

2. Create a jdbc.properties and write JDBC properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/xaf
jdbc.username=root
jdbc.password=root

3. Try writing code

@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
	@Value("${jdbc.url}")
	String url;
	@Value("${jdbc.driverClassName}")
	String driverClassName;
	@Value("${jdbc.username}")
	String username;
	@Value("${jdbc.password}")
	String password;
	@Bean
	public DataSource dataSource() {
		DruidDataSource dataSource = new DruidDataSource();
		dataSource.setUrl(url);
		dataSource.setDriverClassName(driverClassName);
		dataSource.setUsername(username);
		dataSource.setPassword(password);
		return dataSource;
	}
}
@Configuration`Is to declare that our class is a configuration class.

`@PropertySource("classpath:jdbc.properties")`The specified property file path is:`classpath:jdbc.properties`

adopt@value Attribute injection value

adopt@Bean take`dataSource()`Method is declared as a register Bean The method of, Spring The method will be called automatically to add the return value of the method Spring In the container. Default object name id=Method name.

4. Inject @ Autowired

For example, I create a test below:

@RestController
public class HelloController {
	@Autowired
	private DataSource dataSource;
	@GetMapping("hello")
	public String hello() {
		return "hello, spring boot!" + dataSource;
	}
}

At this point, inject the contents of step 3 into the DataSource. After that, the test run time can check whether the injection is successful through debug.

3.2 springBoot attribute injection

In the previous content, we look at using annotations that have not been used before to complete attribute injection. Here, we use springBoot to provide a new attribute injection method, which supports the injection of various java basic data types and complex types.

1. Create a new class for attribute injection:

@ConfigurationProperties(prefix = "jdbc")
public class JdbcProperties {
	private String url;
	private String driverClassName;
	private String username;
	private String password;
	// ... slightly
	// getters and setters
}

First, use the @ ConfigurationProperties(prefix = "jdbc") annotation to declare the current class as a property reading class. When the prefix reads a file, the read data must have a value prefixed with jdbc.

Define each attribute on the class, and the name must be consistent with the part after jdbc. In the attribute file. Pay attention to one point.

Of course, if we do not specify the address of the property file, we need to change the jdbc.properties name to application.properties, which is the property file name read by SpringBoot by default:

2. Create another class to use properties

@Configuration
@EnableConfigurationProperties(JdbcProperties.class)
public class JdbcConfig {
	@Bean
	public DataSource dataSource(JdbcProperties jdbc) {
		DruidDataSource dataSource = new DruidDataSource();
		dataSource.setUrl(jdbc.getUrl());
		dataSource.setDriverClassName(jdbc.getDriverClassName());
		dataSource.setUsername(jdbc.getUsername());
		dataSource.setPassword(jdbc.getPassword());
		return dataSource;
	}
}

Use @ EnableConfigurationProperties(JdbcProperties.class) to declare the object to use the class JdbcProperties

Then you can inject JdbcProperties in the following ways:

  • @Autowired injection
@Autowired
private JdbcProperties prop;
  • Constructor Inject
private JdbcProperties prop;
public JdbcConfig(Jdbcproperties prop){
	this.prop = prop;
}
  • Declare method injection parameters with @ Bean
@Bean
public Datasource dataSource(JdbcProperties prop){
	// ...
}

3.3 springBoot property injection - advantages of @ ConfigurationProperties

  • Relaxed binding: loose binding. It does not strictly require the property name in the property file to be consistent with the member variable name. It supports hump, middle dash, underline and other transformations, and even object guidance.

For example, user.friend.name: represents the name attribute in the friend attribute of the user object. Obviously, friend is also an object@ value annotation is difficult to complete such injection.

  • Meta data support: metadata support, which helps the IDE generate attribute prompts (used when writing open source frameworks).

3.4 optimization

Based on the above injection method, springboot can also optimize the injection.

For example, if only one bean is used for a section of attributes, it can be declared directly where needed:

@Configuration
public class JdbcConfig {
	@Bean
	// Declare the attribute prefix to be injected, and SpringBoot will automatically inject the relevant attributes into the DataSource through the set method
	@ConfigurationProperties(prefix = "jdbc")
	public DataSource dataSource() {
		DruidDataSource dataSource = new DruidDataSource();
		return dataSource;
	}
}

We directly declare @ ConfigurationProperties(prefix = "jdbc") on the method of the @ Bean to be used, and then SpringBoot will automatically call the set method in the Bean method (here is DataSource), and then complete the injection. The premise is that this class must have a set method of the corresponding attribute!

4. Automatic configuration principle

First of all, we will briefly introduce the annotations of the Application startup class introduced above.

4.1 @SpringBootApplication

This annotation is usually placed on the launcher of a project, that is, in the Application class. This annotation is used to inject the startup class into the container, define the scope of container scanning, and load some bean s of the classpath environment.

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

	/**
	 * Exclude specific auto-configuration classes such that they will never be applied.
	 * @return the classes to exclude
	 */
    ...
}

The bold characters marked at the beginning are realized by the annotations from the first line to the third line of the above code.

4.1.1 @SpringBootConfiguration

This annotation indicates that this is a springboot configuration class. Enter again:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}

In the fourth line, we see the fully annotated Configuration @ Configuration, indicating that the initiator is a Configuration class. Click again to enter:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

The @ Component in the fourth line is to inject a bean into the container.

Supplement: in our general study of spring, the following four notes are mentioned:

@controller:    controller Controller layer (injection service)
@service :       service Service layer (injection) dao)
@repository :   dao Persistence layer (Implementation) dao (access)
@component:   Label a class as Spring Container Bean´╝î(Ordinary pojo Instantiate to spring Container, equivalent to in the configuration file<bean id="" class=""/>)

This is why it is possible to inject the boot class into the container and declare it as a springboot configuration class in detail.

4.1.2 @EnableAutoConfiguration

Clicking in may not necessarily understand the meaning of the above annotation. The official description is intercepted here:

/**
 * Enable auto-configuration of the Spring Application Context, attempting to guess and
 * configure beans that you are likely to need. Auto-configuration classes are usually
 * applied based on your classpath and what beans you have defined. For example, if you
 * have {@code tomcat-embedded.jar} on your classpath you are likely to want a
 * {@link TomcatServletWebServerFactory} (unless you have defined your own
 * {@link ServletWebServerFactory} bean).
  • Simply put, it is the use of this annotation. springBoot will guess your use, that is, guess how you want to configure spring
  • If you add a tomcat dependency under your path, this launcher will help you add a tomcat dependency. At this point, automatic configuration will know that you are developing a web application (roughly this means).

This is why Application can define the scope of container scanning. Because it can determine what dependencies you want to use.

4.1.3 @ComponentScan

    @AliasFor("value")
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};
  • Configure instructions for component scanning. It provides functions similar to the < context: component scan > tag. Specify the package to scan through the basepackageclass or basePackages attribute. If these properties are not specified, the package and sub packages will be scanned from the package where the class declaring the annotation is located.
  • Because the class declared by our @ SpringBootApplication annotation is the startup class where the main function is located, the scanned package is the package where the class is located and its sub packages. Therefore, generally, the startup class will be placed in a package directory before comparison, which is why the Application is placed in the front.

This can also indirectly realize the function of loading some beans in the classpath environment. We usually declare a class with @ Bean annotation, so that spring can call it automatically. Then, spring will put the Bean object in its own IOC container. The spring IOC container manages one or more beans. These beans need to be created under the @ Configuration annotation. Using the @ Bean annotation on a method indicates that the method needs to be managed by spring.

4.2 default configuration principle

Here's another reason why sspringboot can complete the corresponding default configuration that takes effect according to the dependencies you introduced?

First, enter the spring boot autoconfiguration dependency:

It can be seen that the introduction of dependency that it can accomplish is far more than web.

Next, enter webmvcoautoconfiguration:

@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

Select a part according to the comments on the contents. The comments here are as follows:

  • @Configuration: declare that this class is a configuration class
  • @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })

The condition here is OnClass, that is, it satisfies the existence of the following classes: Servlet, DispatcherServlet and WebMvcConfigurer. As long as tomcat dependency is introduced into Servlet, it will naturally exist, and spring MVC will be introduced into the latter two. Here is to judge whether you have introduced related dependencies. After the dependency is introduced, the condition is established, and the configuration of the current class will take effect!

  • @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

This condition is different from the above. It means that it takes effect only when there is no specified Bean in the environment. The meaning is the same as above.

summary

The above is an introduction to SpringBoot injection configuration, which will be briefly introduced according to the integration with other mainstream frameworks. Thank you for reading.

Tags: Java Spring Spring Boot

Posted on Sat, 09 Oct 2021 05:12:42 -0400 by InfinityRogue