别人写从0开始实现xxx,我从-1开始更牛逼。
今天,我们先来教大家如何实现一个中间件。
新项目
首先,我们创建一个用于测试的多模块项目。
项目包含两个模块,test-infra用户中间件模块开发,demo进行测试。
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.7.0
com.aixiaoxian.infra
aixiaoxian-infra
0.0.1-SNAPSHOT
aixiaoxian-infra
aixiaoxian-infra
pom
1.8
demo
test-infra
maven-source-plugin
true
package
jar-no-fork
开发中间件
项目创建OK,接下来开始开发最简单的中间件。
在resources目录下创建一个META-INFA/spring.factories文件用于自动组装,不要问我什么是自动组装,然后配置一个自动组装类。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.aixiaoxian.testInfra.config.TestConfiguration
实现TestConfiguration最简单的方法是使用@Bean注解声明一个bean,交给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;
}
}
然后实现TestManager,真正的中间件逻辑的处理部分。
@Slf4j
public class TestManager {
public TestManager() {
init();
}
public void init(){
log.info("TestManager start");
}
}
本例中最简单的中间件就开发完成了,添加到demo模块开始测试即可。
com.aixiaoxian.infra
test-infra
0.0.1-SNAPSHOT
改变位置
我们换个姿势创建Bean,使用BeanDefinitionRegistryPostProcessor,让TestConfiguration实现,重写postProcessBeanDefinitionRegistry,注册一个新的Bean aiManager。
@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");
}
}
另一个职位
对自动装配创建Bean有基本的了解,如果我想声明一个注解给别人使用怎么办?
首先创建一个注解,注意我使用了@Import注解,TestImportSelector实现了TestImportSelector接口。
@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 的写法也很简单,也实现了自动组装。当然用上面的写法也可以达到同样的效果,但是建议这样写,不问,问就行。
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");
}
}
最后,将我们的注解放在演示启动类上。
@SpringBootApplication
@TestAnnotation
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
终于可以看到输出了:
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
好的,就是这样,我猜没有人需要这个源代码吧?为了后面的文章,我会写这个铺垫和结束。
暂无评论内容