Others write to start from 0 to realize xxx, I start from -1 to be more awesome.
Today, let's start by teaching you how to implement a middleware.
New Project
First, we create a new multi-module project for testing.
The project contains two modules, test-infra
development of user middleware module, demo
for testing.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.aixiaoxian.infra</groupId>
<artifactId>aixiaoxian-infra</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>aixiaoxian-infra</name>
<description>aixiaoxian-infra</description>
<packaging>pom</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<modules>
<module>demo</module>
<module>test-infra</module>
</modules>
<dependencies>
</dependencies>
<build>
<plugins>
<!-- Source -->
<plugin>
<artifactId>maven-source-plugin</artifactId>
<inherited>true</inherited>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
development middleware
The project creation is OK, and then start to develop the simplest middleware.
Create a META-INFA/spring.factories
file in the resources
directory for automatic assembly, don't ask me what is automatic assembly, and then configure an automatic assembly class.
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.aixiaoxian.testInfra.config.TestConfiguration
Implement TestConfiguration
, the easiest way, directly use @Bean
annotation to declare a bean to be managed by Spring.
@Configuration
public class TestConfiguration implements BeanDefinitionRegistryPostProcessor, EnvironmentAware {
private Environment environment;
@Bean
public TestManager getTestManager() {
return new TestManager();
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
}
Then implement the processing part of the real middleware logic TestManager
.
@Slf4j
public class TestManager {
public TestManager() {
init();
}
public void init(){
log.info("TestManager start");
}
}
In this case, the simplest middleware has been developed, just add it to the demo
module and start the test.
<dependency>
<groupId>com.aixiaoxian.infra</groupId>
<artifactId>test-infra</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
change posture
Bean
53ac0c54417465a3578e7a4962444314--- , BeanDefinitionRegistryPostProcessor
,让TestConfiguration
去实现它,重写postProcessBeanDefinitionRegistry
,注册一个新的Bean aiManager
, this is also OK, there are many ways to write it, so I won't repeat it.
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(AiManager.class);
beanDefinitionBuilder.addConstructorArgValue(this.environment);
beanDefinitionRegistry.registerBeanDefinition("aiManager", beanDefinitionBuilder.getBeanDefinition());
}
@Slf4j
public class AiManager {
private Environment environment;
public AiManager(Environment environment) {
this.environment = environment;
init();
}
public void init(){
log.info("AiManager start");
}
}
change posture
With a basic understanding of Bean creation by autowiring, what should I do if I want to declare an annotation for others to use?
First create an annotation, notice that I used the @Import
annotation, TestImportSelector
implemented TestImportSelector
interface.
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({TestImportSelector.class})
@Documented
public @interface TestAnnotation {
}
public class TestImportSelector implements DeferredImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{AnnotationConfiguration.class.getName()};
}
}
AnnotationConfiguration
writing method is also very simple, which also realizes automatic assembly. Of course, you can achieve the same effect if you use the above writing method, but it is recommended to write it like this, don't ask, just ask.
public class AnnotationConfiguration implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(AnnotationManager.class);
beanDefinitionRegistry.registerBeanDefinition("annotationManager", beanDefinitionBuilder.getBeanDefinition());
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
}
@Slf4j
public class AnnotationManager {
public AnnotationManager() {
init();
}
public void init(){
log.info("AnnotationManager start");
}
}
Finally, put our annotation on the demo
startup class.
@SpringBootApplication
@TestAnnotation
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Finally we can see the output:
2022-06-21 19:05:07.433 INFO 4598 --- [ main] c.a.testInfra.manager.TestManager : TestManager start
2022-06-21 19:05:07.456 INFO 4598 --- [ main] c.a.testInfra.manager.AiManager : AiManager start
2022-06-21 19:05:07.456 INFO 4598 --- [ main] c.a.testInfra.manager.AnnotationManager : AnnotationManager start
Okay, that's it, I guess, no one needs this source code? For the sake of the following articles, I will write this foreshadowing and end.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。