Spring相关

79 阅读8分钟

1、常用注解

@ComponentScan:指定spring的扫描路径,会处理路径上含有@Component注解的类

@Component:交由spring管理

@Configuration:标记当前类是配置类,里面@Bean的方法,会被spring实例化成bean

@Bean:配置类中注册bean的标识,加在方法上,方法名作为beanName,对象作为bean

//自动从配置文件加载信息到对象并生成bean
@Component
@ConfigurationProperties(prefix = "app")
public class AppConfig {
    private String name;
    private String version;
    private String description;

    // getters and setters (必须要有setter方法,因为绑定是通过setter进行的)
}


//从配置文件读取特定的值
@Value("${app.version}")
    private String appVersion;

2、springboot自动装配机制

Spring Boot 的自动装配是其核心特性之一,它极大地简化了基于 Spring 的应用开发,让你无需手动配置大量 XML 或 Java Config 就能使用各种功能。其核心思想是  “约定优于配置”  和  “按需加载” 。下面详细解析其流程:

核心触发点:@SpringBootApplication

  1. 启动类注解:  你的应用入口类(通常有 main 方法)会被标注 @SpringBootApplication

  2. 元注解:  @SpringBootApplication 本身是一个复合注解,它包含三个关键注解:

    • @SpringBootConfiguration: 本质上是 @Configuration,标记该类为 Spring 的配置类。
    • @ComponentScan: 启用组件扫描,默认扫描启动类所在包及其子包下的 @Component@Service@Repository@Controller 等注解的类,并将它们注册为 Spring Bean。
    • @EnableAutoConfiguration: 这是开启自动装配的“总开关”!

自动装配的核心引擎:@EnableAutoConfiguration

  1. 导入 AutoConfigurationImportSelector:
    @EnableAutoConfiguration 注解通过 @Import(AutoConfigurationImportSelector.class) 导入了 AutoConfigurationImportSelector 这个关键的类。这个类负责决定哪些自动配置类应该被加载到 Spring 应用上下文中。

  2. 加载候选配置类列表:
    AutoConfigurationImportSelector 的核心方法是 selectImports()。这个方法内部会调用 getAutoConfigurationEntry()

    • 关键步骤:  使用 SpringFactoriesLoader.loadFactoryNames() 方法。

    • 查找位置:  这个方法会扫描类路径下 META-INF/spring.factories 文件。

    • 查找键:  查找文件中键为 org.springframework.boot.autoconfigure.EnableAutoConfiguration 对应的值。

    • 获取值:  这个值是一个逗号分隔的全限定类名列表,包含了 Spring Boot 及其 Starter 提供的所有可能的自动配置类 (XXXAutoConfiguration)。例如:

      properties

      # META-INF/spring.factories (通常在 spring-boot-autoconfigure jar 中)
      org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
      org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
      org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
      org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
      org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
      org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
      ... # 非常长的列表
      
  3. 过滤候选配置类:
    获取到庞大的候选配置类列表后,并不是所有都会被加载。Spring Boot 会进行严格过滤,只加载满足当前应用环境条件的配置类。过滤主要通过 @Conditional 及其众多派生注解(条件注解)实现:

    • @ConditionalOnClass  类路径下存在指定的类时才生效。(例如:DataSource.classRedisTemplate.class)
    • @ConditionalOnMissingBean  当 Spring 容器中不存在指定类型或名称的 Bean 时才生效。这是保证用户自定义配置优先的关键!
    • @ConditionalOnProperty  指定的配置属性存在且有特定值时才生效。(例如:spring.datasource.url)
    • @ConditionalOnWebApplication / @ConditionalOnNotWebApplication  根据是否是 Web 应用决定是否生效。
    • @ConditionalOnResource  类路径下存在指定的资源文件时才生效。
    • @ConditionalOnJava  运行在指定的 Java 版本上才生效。
    • @ConditionalOnCloudPlatform  运行在指定的云平台上才生效。
    • @ConditionalOnSingleCandidate  当容器中存在且只存在一个指定类型的 Bean,或者虽然有多个但有一个是首选时才生效。
    • @AutoConfigureAfter / @AutoConfigureBefore / @AutoConfigureOrder  控制自动配置类的加载顺序。

    过滤过程:  AutoConfigurationImportSelector 利用 ConfigurationClassFilter 结合上述条件注解,对第 2 步获取的所有候选配置类进行逐一检查。只有全部条件都满足的自动配置类,最终才会被导入到 Spring 应用上下文中。

  4. 导入并处理选中的自动配置类:
    经过过滤后剩下的自动配置类 (XXXAutoConfiguration),会被 @EnableAutoConfiguration 通过 @Import 机制导入,成为 Spring 应用上下文中的配置类 (@Configuration)。

  5. 自动配置类的作用:
    每个自动配置类 (XXXAutoConfiguration) 本身就是一个标准的 Spring @Configuration 类。它的主要职责是:

    • 定义 Bean:  使用 @Bean 方法创建和配置特定功能所需的组件(如 DataSourceRestTemplateJdbcTemplateRedisTemplateServletWebServerFactory 等)。

    • 应用默认配置:  读取 application.properties/application.yml 中的相关属性(通过 @EnableConfigurationProperties 和 @ConfigurationProperties),并应用到这些 Bean 上。

    • 内部依赖管理:  一个自动配置类内部可能会依赖其他自动配置类创建的 Bean。

    • 条件保护:  关键!  自动配置类本身或其内部的 @Bean 方法通常会再次使用 @Conditional 注解进行保护。这是双保险:

      • 类级别的条件确保整个配置类只在满足特定条件时才被处理。
      • @Bean 方法级别的条件确保即使配置类被加载了,其中的某个 Bean 也只在满足更细粒度条件时才被创建。这确保了按需创建 Bean,避免不必要的开销和冲突。

自动装配流程总结

  1. 启动:  应用启动,执行 SpringApplication.run(...)

  2. 识别配置类:  Spring 容器启动,识别到启动类上的 @SpringBootApplication

  3. 组件扫描:  执行 @ComponentScan,注册用户定义的 Bean(@Component@Service 等)。

  4. 启用自动装配:  @EnableAutoConfiguration 生效。

  5. 加载候选列表:  AutoConfigurationImportSelector 扫描所有 META-INF/spring.factories 文件,获取 EnableAutoConfiguration 键下的所有自动配置类全名。

  6. 条件过滤:  利用 @Conditional 及其派生注解对候选自动配置类进行严格过滤,移除不满足当前应用环境条件的配置类。

  7. 导入配置类:  将过滤后剩下的自动配置类作为 @Configuration 类导入到 Spring 应用上下文中。

  8. 处理自动配置类:  Spring 容器处理这些导入的自动配置类:

    • 解析类级别 @Conditional(如果还有)。
    • 处理 @Bean 方法:对每个 @Bean 方法,检查其上的 @Conditional 注解条件是否满足。
    • 条件满足:  执行 @Bean 方法,将返回的对象注册为 Spring Bean。
    • 条件不满足:  跳过该 @Bean 方法。
  9. 完成装配:  所有被导入且满足条件的自动配置类处理完毕,它们定义的 Bean(满足方法级别条件)被注册到容器中。此时,应用所需的基础设施(数据源、Web 服务器、模板引擎、缓存管理器等)以及 Starter 提供的功能 Bean 已自动配置好。

  10. 用户自定义配置优先:  在整个过程中,@ConditionalOnMissingBean 注解保证了如果用户已经在自己的配置类(@Configuration)或通过 @ComponentScan 扫描到的类中显式定义了某个 Bean(例如自己 @Bean 了一个 DataSource),那么自动配置类中定义的同类型 Bean 将不会被创建。这是 Spring Boot 自动装配非入侵性可定制性的关键。

关键点与优势

  • 约定优于配置:  提供合理的默认值,开箱即用。
  • 按需加载:  通过强大的 @Conditional 机制,只加载和创建当前应用真正需要的配置和 Bean,避免不必要的资源消耗和冲突。
  • 非入侵性:  @ConditionalOnMissingBean 确保用户自定义配置总是优先于自动配置。
  • Starter 简化依赖:  Starter 打包了特定功能所需的依赖和自动配置类。引入一个 Starter,就自动引入了相关依赖,并触发对应的自动配置。
  • 高度可定制:  通过 application.properties/application.yml 可以轻松覆盖自动配置的默认值。通过自定义 @Configuration 类或 @Bean 方法可以完全替代自动配置。

理解 Spring Boot 自动装配的流程,特别是 @EnableAutoConfigurationAutoConfigurationImportSelectorspring.factories 和 @Conditional 注解的作用,是掌握 Spring Boot 原理和进行高效开发调试的关键。

3、spring生命周期

  1. 创建对象:寻找构造方法,如果没有无参构造方法,将有参构造方法的参数作为属性装载到bean中
  2. 注入属性
  3. BeanNameAware回调接口,可以获得bean的name
  4. BeanPostProcessor接口的postProcessBeforeInitialization()
  5. 初始化:@PostConstruct注解标记的方法执行,执行InitializingBean接口afterPropertiesSet()
  6. BeanPostProcessor接口的postProcessAfterInitialization() 7、销毁 如果一个 Bean 同时使用了多种销毁钩子,它们的执行顺序是: 使用 @PreDestroy 注解的方法 实现 DisposableBean 接口的 destroy() 方法 自定义配置的销毁方法(通过 XML 或 @Bean 注解)

4、springmvc收到一个请求后的执行流程

  1. spring启动时,扫描所有@Controller、@RestController注解的类,构建一个map,保存到RequestMappingHandlerMapping类中
Map<RequestMappingInfo, HandlerMethod> mappingRegistry;

// 对于你的方法,这个 Map 中会存入类似这样的一条记录:
Key (RequestMappingInfo): 
    - patterns: "/eventMessageConsume"
    - methods: [ANY] // 因为你没指定,所以匹配所有HTTP方法
Value (HandlerMethod):
    - bean: 你的Controller类的实例(由Spring IOC容器创建并管理)
    - method: java.lang.reflect.Method 对象(指向 eventMessageConsume 这个方法)
    - parameters: [Parameter("eventMessage")] // 方法参数信息
  1. DispatcherServlet 接收到请求,询问所有的handlerMapping实现类,谁能处理,找到RequestMappingHandlerMapping,将该接口的拦截器(intercetor)和方法信息构建成HandlerExecutionChain打包返回
  2. DispatcherServlet 拿到 HandlerExecutionChain 后,开始找能执行它的 HandlerAdapter寻找适配器RequestMappingHandlerAdapter 说:“我能执行这种 @RequestMapping 的方法”。RequestMappingHandlerAdapter找到参数处理器,比如@RequestParam的处理器进行参数解析。
  3. 通过反射的方式执行
// 伪代码,体现 HandlerAdapter 内部的逻辑
Object[] args = new Object[]{"abc"}; // 解析得到的参数值
HandlerMethod handlerMethod = ...; // 之前找到的“说明书”

// 最关键的一行:通过反射调用目标方法
Object returnValue = handlerMethod.getMethod().invoke(
    handlerMethod.getBean(), // 你的Controller对象(从IOC容器来的)
    args                     // 参数值数组
);

5.返回结果