谈谈Spring boot 启动层面的开发

简介:

Spring boot的启动可以主要分为2个阶段。1 是调用AbstractApplicationContext的refresh方法之前和调用AbstractApplicationContext的refresh。 我们知道AbstractApplicationContext的refresh的方法是一个模板方法。几乎所有类型的ApplicationContext的初始化都是围绕这个refresh方法来进行。

1. refresh方法之前

1.1 ApplicationContextInitializer

这个类Spring boot最先进行调用的类,其主要就是初始化一些BeanFactoryPostProcessor(后面会说明),或者一些在Application 初始化的时候就需要做的事情。而这些类通过通过扫描calsspath路径下的:META-INF/spring.factories 文件中的org.springframework.context.ApplicationContextInitializer字来加载类的全路径名,通过反射获取对象,然后调用initialize方法。

1.2 ApplicationListener

这个和ApplicationContextInitializer加载的方式类似,也是从META-INF/spring.factories文件中的配置,主要作用就是在Spring boot的初始化不同阶段会处罚不同的事件(ApplicationEvent及其子类),而这些监听器就会根据自己在不同事件触发的情况下完成自己的处理逻辑。例如,ConfigFileApplicationListener负责加载配置文件。

当然也可以通过其他方式加入beanFactory中,详情可以参照BeanFactoryPostProcessor加入到beanFactory的方法

1.ApplicationListener的有些事件是在ApplicationContextInitializer之前触发的

2.建议不要直接在ApplicationContextInitializer加入自己的BeanFactoryPostProcessor方法,xxxAware是不会帮你注入的。

2. refresh方法

这个就是spring的模板方法,主要有3个比较重要的接口

2.1 BeanFactoryPostProcessor

public interface BeanFactoryPostProcessor {
    
   void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

这个方法就是给可以对beanFactory进行一些自定义的操作,例如加入一些bean等。当然前提就是我们定义的bean是在beanFactory中。有许多办法可以做到

  •  在ApplicationContextInitializer中定义加入,例如
public class MyContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    public void initialize(ConfigurableApplicationContext applicationContext) {
        applicationContext.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
    }

}
  • 通过其他BeanFactoryPostProcessor加入,可以通过注解@Import或者加载XML)

例如通过@Import(value={AnnotationBeanDefinitionRegistrar.class})

@Configuration
public class AnnotationBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    private String BEAN_NAME = "annotationBeanPostProcessor";

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        List<String> basePackages = getPackagesToScan(importingClassMetadata);
        if (!registry.containsBeanDefinition(BEAN_NAME)) {
            addPostProcessor(registry, basePackages);
        }
    }

    private void addPostProcessor(BeanDefinitionRegistry registry, List<String> basePackages) {
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(AnnotationBeanPostProcessor.class);
        beanDefinition.getConstructorArgumentValues()
                .addGenericArgumentValue(basePackages);
        beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        registry.registerBeanDefinition(BEAN_NAME, beanDefinition);
    }


    private List<String> getPackagesToScan(AnnotationMetadata metadata) {
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                metadata.getAnnotationAttributes(EnableDubbo.class.getName()));
        String[] basePackages = attributes.getStringArray("basePackages");
        return Arrays.asList(basePackages);
    }
}

这样,就可以加入我们自定义的BeanFactoryPostProcessor,就可以在Bean注册的层面上进行开发

2.2 BeanPostProcessor

public interface BeanPostProcessor {
  
   Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

   Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

这个接口主要就是针对在bean实例化前后做一些定制开发。一般只针对某个接口或者某个注解进行批量操作

3. 综述

1. 如果你需要在SpringApplication初始化的时候就做一些事情,使用ApplicationContextInitializer

2. 如果你需要SpringApplication的某个特定阶段做一些事情,使用ApplicationListener(推荐)

3. 如果你需要在beanFactory层面上开发,使用BeanFactoryPostProcessor(推荐)

4. 如果你需要在对某个bean的实例化层面上开发,使用BeanPostProcessor(一般业务上的开发使用InitializingBean或者init-method能够满足)


作者:lizo

来源:51CTO

相关文章
|
2月前
|
XML 存储 缓存
【深入浅出Spring原理及实战】「缓存Cache开发系列」带你深入分析Spring所提供的缓存Cache管理器的实战开发指南(修正篇)
【深入浅出Spring原理及实战】「缓存Cache开发系列」带你深入分析Spring所提供的缓存Cache管理器的实战开发指南(修正篇)
35 0
|
1月前
|
开发框架 安全 Java
探索 Spring 框架:企业级应用开发的强大工具
探索 Spring 框架:企业级应用开发的强大工具
38 2
|
6天前
|
前端开发 安全 Java
使用Spring框架加速Java开发
使用Spring框架加速Java开发
52 0
|
7天前
|
传感器 人工智能 前端开发
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
智慧校园电子班牌,坐落于班级的门口,适合于各类型学校的场景应用,班级学校日常内容更新可由班级自行管理,也可由学校统一管理。让我们一起看看,电子班牌有哪些功能呢?
99 4
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
|
16天前
|
IDE Java 开发工具
Spring Boot DevTools:加速开发的热部署工具
【4月更文挑战第28天】在Spring Boot的开发过程中,快速反馈和效率至关重要。Spring Boot DevTools是一个为开发者设计的模块,支持热部署(hot swapping),能够实现应用的快速重启和自动重载,极大地提高了开发效率。本篇博客将介绍Spring Boot DevTools的核心概念,并通过具体的实战示例展示如何在开发过程中利用这一工具。
24 0
|
20天前
|
开发框架 前端开发 安全
Java从入门到精通:2.2.2学习使用Spring框架进行Web应用开发
Java从入门到精通:2.2.2学习使用Spring框架进行Web应用开发
|
26天前
|
监控 Java 测试技术
使用 Spring Boot 简化企业级应用开发
【4月更文挑战第19天】Spring Boot简化企业级应用开发,加速项目初始化与配置,轻松集成多种技术,降低依赖管理复杂性。它提高开发效率,具备灵活扩展性,便于监控管理,且高度可测试。强大的社区支持解决问题迅速,助力企业快速推出高质量应用,提升市场竞争力。开发者掌握Spring Boot能增强自身价值。
|
26天前
|
前端开发 Java 应用服务中间件
选择 Spring Boot 进行微服务开发的 7 大理由
选择 Spring Boot 进行微服务开发的 7 大理由
22 1
|
26天前
|
运维 自然语言处理 安全
Spring Boot 底层级探索系列 04 - Web 开发(3)
Spring Boot 底层级探索系列 04 - Web 开发(3)
27 0
|
26天前
|
JSON Java fastjson
Spring Boot 底层级探索系列 04 - Web 开发(2)
Spring Boot 底层级探索系列 04 - Web 开发(2)
31 0