Learn how to manage your own components with spring cloud/boot

case,

Function:

You need to write a component that reports data to kafka.

 

When the build starts, the following resources need to be created:

1. Establish several connections with kafka

2. Start a thread pool

3. Start reporting a buffer

 

Questions are as follows:

 

1. How to introduce the component in the spring project and inject it into the spring container

2. If it is indirectly referenced to this JAR package (for example, the referenced project is referenced here to form a JAR), or if you just want to use the data type in it, but do not intend to use the function, how to prevent the resource from starting automatically with the introduction. waste of resources

3. How to uniformly manage the configuration of the formation

4. How to manage many JAR package dependencies, for example, 0.11.0.2 of kafka is needed for this component development, and it needs to be upgraded to 1.0.0 one day

 

In fact, there are better solutions to these problems in spring cloud, such as zuul, and the latter is also a solution to imitate zuul

 

1. How to make this component be introduced by the spring project

 

SPI method,

as zuul's pass

\META-INF\spring.factories 

Import, specify the boot directory

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration,\
org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration

 

Therefore, the composition is also defined as follows

\META-INF\spring.factories 

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.zhenai.security.report.SecurityAutoConfiguration

In SecurityAutoConfiguration, beans are initialized as needed, and related resources are started. Such as starting a connection, starting a local thread pool, etc.

But the problem here is that as long as this JAR package is introduced (including the indirect introduction of the JAR package), then all projects will connect to kafka for no reason and start some useless thread pools

 

Second, how to shield the project startup-related resources that are indirectly referenced to this JAR package

 

To solve this problem, spring cloud and spring boot are slightly different, look at spring cloud first.

 

Marker method

spring cloud label pattern

Let's first see how zuul does it. If you want to start ZUUL in the project, you usually add the @EnableZuulProxy tag to the main class, as follows:

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class Application {
...  ....
}

 

Need to introduce @EnableZuulProxy tag

The source code of @EnableZuulProxy is as follows:

@EnableCircuitBreaker
@EnableDiscoveryClient
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyMarkerConfiguration.class)
public @interface EnableZuulProxy {
}

 

See @Import(ZuulProxyMarkerConfiguration.class), ZuulProxyMarkerConfiguration only does one thing, introducing a maker tag

as follows:

@Configuration
public class ZuulProxyMarkerConfiguration {
	@Bean
	public Marker zuulProxyMarkerBean() {
		return new Marker();
	}

	class Marker {
	}
}

 

This Maker object is used to enable the configuration, thus controlling whether the resource is started, such as ZuulServerAutoConfiguration

@Configuration
@EnableConfigurationProperties({ ZuulProperties.class })
@ConditionalOnClass(ZuulServlet.class)
@ConditionalOnBean(ZuulServerMarkerConfiguration.Marker.class)
// Make sure to get the ServerProperties from the same place as a normal web app would
@Import(ServerPropertiesAutoConfiguration.class)
public class ZuulServerAutoConfiguration {
...  ...
}

 

According to whether there is a Marker to inject related classes, whether to start.

 

Therefore:

Here, the components in the case also choose this way, such as

@EnableZASecurityReport tag

When you need to start, you can add a label to the main class, such as

@EnableZASecurityReport
public class Application {

...  ....

}

 

Whether the subsequent kafka connection class, thread pool, buffer, etc. are allocated can be managed according to the relevant identifiers, such as the spi entry class SecurityAutoConfiguration:

@Configuration
@EnableConfigurationProperties({ SecurityReportProperties.class })
@ConditionalOnBean(SecurityProxyMarkerConfiguration.Marker.class)
public class SecurityAutoConfiguration {
...  ... 
}

In this way, if @EnableZASecurityReport is not added in the main startup class, even if the JAR package of the component is introduced, the related resources will not be started.

 

starter method

There is another way, that is, spring boot uses more start methods

All configurations of spring boot are in spring-boot-autoconfigure/META-INF/spring.factories, and whether to start the resource is determined by whether the @ConditionalOnBean specific class is introduced.

如: spring-boot-starter-data-redis

First, through spring.factories, the boot class of Redis is introduced

org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\

Such as:

RedisAutoConfiguration

@Configuration
@ConditionalOnClass({ RedisOperations.class })
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
 ... ...
}

 

When the project needs to use Redis, introduce related classes through Maven

<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-redis</artifactId>  
</dependency>  

spring-boot-starter-data-redis is actually an empty project. There is spring.provides, through which redis-related JAR packages are introduced, and then @ConditionalOnClass is enabled to complete the initialization of the Redis JAR environment.

 

3. How to manage the configuration in a unified way

After a component (JAR package) comes out, there will be more configurations. For example, the project involves a lot of kafka configuration, thread pool configuration, etc. The traditional way is to write a relevant documentation, a bunch of configuration items will make it very easy to use trouble.

 

1. Convention is better than configuration

In spring cloud/boot, the most useful thing is that  convention is better than configuration. Remember conventions, write less configuration

For example, in zuul, only a few necessary items need to be configured, and the others are convention items

For example, the convention configuration file is application.yml (or bootstrap.yml):

zuul:
 debug:
  routes:
    ZHENAI-CLIENT:
      path: /test/**

 

Simply configure the routes to start. If you want to find the agreed value of Zuul's configuration, you can directly look for the general configuration class ZuulProperties.

In ZuulProperties, all configuration items are included, and modules are divided by configuring objects, such as:

ZuulRoute related, Host related, HystrixSemaphore related, etc.

(also a default convention)

Therefore,

In components, it is also possible to simulate simplified configuration. The core function of this component is reporting. The matching project should only be the address of kafka. To enable it, you only need to

report.kafkaConfig.servers=X.X.X.X:9092

That is, if you want to configure in detail, and the agreed value, use a unified configuration file to manage ReportProperties.java

It indicates the value of the agreed configuration

 

2. Use spring's automatic assembly function

Autowiring using the @ConfigurationProperties tag. All the basic functions of this are not elaborated.

Details can be found in ZuulProperties.

The benefits are:

1. Dynamic configuration can be achieved, such as configuring map, list, and even enums, etc.

2. If you cooperate with spring cloud config, you can achieve dynamic hot update

 

Fourth, unified management of dependencies of JAR packages

Referring to spring cloud/boot, JAR files are managed separately in the spring-boot-dependencies project, and the compatibility between versions relies on the open source project http://platform.spring.io/platform/ for management, so it is very There are few version conflicts.

As a self-developed component, it is best to rely on spring boot to manage the version number of the third-party jars, and other jars that need to be used can be managed separately by establishing a dependencies project, and you can no longer write the version number for your own project. , which is convenient for unified upgrade and maintenance.

 

 

To summarize:

1. How to provide components for the spring /spring boot project would be better

Using SPI mode, it is convenient for smooth reference

2. How to avoid automatic startup of component-related resources after projects that do not need to use components refer to JAR by mistake

1. Provide @EnableXXX tag mode, inject a marker tag, and judge by @ConditionalOnBean at startup

2. The starter method, the configuration is separated from the class, and @ConditionalOnBean is used to judge, and the session will be started only when referenced at the same time.

3. How to manage the configuration of components in a unified way

1. The convention is greater than the configuration, and the configuration is simplified. Unify a component's XXXProperties.java for each component and provide agreed values

2. Automatic assembly mode

4. How to manage JAR packages in a unified way to prevent JAR version conflicts, etc.

Give it to spring boot for unified management, and other version numbers are unified in the parent project (or join the dependencies project) Management version

 

 

Add an advertisement. In the new year, I plan to maintain the official account and improve the quality.

Welcome to follow, thank you

Guess you like

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