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
-
启动类注解: 你的应用入口类(通常有
main方法)会被标注@SpringBootApplication。 -
元注解:
@SpringBootApplication本身是一个复合注解,它包含三个关键注解:@SpringBootConfiguration: 本质上是@Configuration,标记该类为 Spring 的配置类。@ComponentScan: 启用组件扫描,默认扫描启动类所在包及其子包下的@Component,@Service,@Repository,@Controller等注解的类,并将它们注册为 Spring Bean。@EnableAutoConfiguration: 这是开启自动装配的“总开关”!
自动装配的核心引擎:@EnableAutoConfiguration
-
导入 AutoConfigurationImportSelector:
@EnableAutoConfiguration注解通过@Import(AutoConfigurationImportSelector.class)导入了AutoConfigurationImportSelector这个关键的类。这个类负责决定哪些自动配置类应该被加载到 Spring 应用上下文中。 -
加载候选配置类列表:
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,\ ... # 非常长的列表
-
-
过滤候选配置类:
获取到庞大的候选配置类列表后,并不是所有都会被加载。Spring Boot 会进行严格过滤,只加载满足当前应用环境条件的配置类。过滤主要通过@Conditional及其众多派生注解(条件注解)实现:@ConditionalOnClass: 类路径下存在指定的类时才生效。(例如:DataSource.class,RedisTemplate.class)@ConditionalOnMissingBean: 当 Spring 容器中不存在指定类型或名称的 Bean 时才生效。这是保证用户自定义配置优先的关键!@ConditionalOnProperty: 指定的配置属性存在且有特定值时才生效。(例如:spring.datasource.url)@ConditionalOnWebApplication/@ConditionalOnNotWebApplication: 根据是否是 Web 应用决定是否生效。@ConditionalOnResource: 类路径下存在指定的资源文件时才生效。@ConditionalOnJava: 运行在指定的 Java 版本上才生效。@ConditionalOnCloudPlatform: 运行在指定的云平台上才生效。@ConditionalOnSingleCandidate: 当容器中存在且只存在一个指定类型的 Bean,或者虽然有多个但有一个是首选时才生效。@AutoConfigureAfter/@AutoConfigureBefore/@AutoConfigureOrder: 控制自动配置类的加载顺序。
过滤过程:
AutoConfigurationImportSelector利用ConfigurationClassFilter结合上述条件注解,对第 2 步获取的所有候选配置类进行逐一检查。只有全部条件都满足的自动配置类,最终才会被导入到 Spring 应用上下文中。 -
导入并处理选中的自动配置类:
经过过滤后剩下的自动配置类 (XXXAutoConfiguration),会被@EnableAutoConfiguration通过@Import机制导入,成为 Spring 应用上下文中的配置类 (@Configuration)。 -
自动配置类的作用:
每个自动配置类 (XXXAutoConfiguration) 本身就是一个标准的 Spring@Configuration类。它的主要职责是:-
定义 Bean: 使用
@Bean方法创建和配置特定功能所需的组件(如DataSource,RestTemplate,JdbcTemplate,RedisTemplate,ServletWebServerFactory等)。 -
应用默认配置: 读取
application.properties/application.yml中的相关属性(通过@EnableConfigurationProperties和@ConfigurationProperties),并应用到这些 Bean 上。 -
内部依赖管理: 一个自动配置类内部可能会依赖其他自动配置类创建的 Bean。
-
条件保护: 关键! 自动配置类本身或其内部的
@Bean方法通常会再次使用@Conditional注解进行保护。这是双保险:- 类级别的条件确保整个配置类只在满足特定条件时才被处理。
@Bean方法级别的条件确保即使配置类被加载了,其中的某个 Bean 也只在满足更细粒度条件时才被创建。这确保了按需创建 Bean,避免不必要的开销和冲突。
-
自动装配流程总结
-
启动: 应用启动,执行
SpringApplication.run(...)。 -
识别配置类: Spring 容器启动,识别到启动类上的
@SpringBootApplication。 -
组件扫描: 执行
@ComponentScan,注册用户定义的 Bean(@Component,@Service等)。 -
启用自动装配:
@EnableAutoConfiguration生效。 -
加载候选列表:
AutoConfigurationImportSelector扫描所有META-INF/spring.factories文件,获取EnableAutoConfiguration键下的所有自动配置类全名。 -
条件过滤: 利用
@Conditional及其派生注解对候选自动配置类进行严格过滤,移除不满足当前应用环境条件的配置类。 -
导入配置类: 将过滤后剩下的自动配置类作为
@Configuration类导入到 Spring 应用上下文中。 -
处理自动配置类: Spring 容器处理这些导入的自动配置类:
- 解析类级别
@Conditional(如果还有)。 - 处理
@Bean方法:对每个@Bean方法,检查其上的@Conditional注解条件是否满足。 - 条件满足: 执行
@Bean方法,将返回的对象注册为 Spring Bean。 - 条件不满足: 跳过该
@Bean方法。
- 解析类级别
-
完成装配: 所有被导入且满足条件的自动配置类处理完毕,它们定义的 Bean(满足方法级别条件)被注册到容器中。此时,应用所需的基础设施(数据源、Web 服务器、模板引擎、缓存管理器等)以及 Starter 提供的功能 Bean 已自动配置好。
-
用户自定义配置优先: 在整个过程中,
@ConditionalOnMissingBean注解保证了如果用户已经在自己的配置类(@Configuration)或通过@ComponentScan扫描到的类中显式定义了某个 Bean(例如自己@Bean了一个DataSource),那么自动配置类中定义的同类型 Bean 将不会被创建。这是 Spring Boot 自动装配非入侵性和可定制性的关键。
关键点与优势
- 约定优于配置: 提供合理的默认值,开箱即用。
- 按需加载: 通过强大的
@Conditional机制,只加载和创建当前应用真正需要的配置和 Bean,避免不必要的资源消耗和冲突。 - 非入侵性:
@ConditionalOnMissingBean确保用户自定义配置总是优先于自动配置。 - Starter 简化依赖: Starter 打包了特定功能所需的依赖和自动配置类。引入一个 Starter,就自动引入了相关依赖,并触发对应的自动配置。
- 高度可定制: 通过
application.properties/application.yml可以轻松覆盖自动配置的默认值。通过自定义@Configuration类或@Bean方法可以完全替代自动配置。
理解 Spring Boot 自动装配的流程,特别是 @EnableAutoConfiguration、AutoConfigurationImportSelector、spring.factories 和 @Conditional 注解的作用,是掌握 Spring Boot 原理和进行高效开发调试的关键。
3、spring生命周期
- 创建对象:寻找构造方法,如果没有无参构造方法,将有参构造方法的参数作为属性装载到bean中
- 注入属性
- BeanNameAware回调接口,可以获得bean的name
- BeanPostProcessor接口的postProcessBeforeInitialization()
- 初始化:@PostConstruct注解标记的方法执行,执行InitializingBean接口afterPropertiesSet()
- BeanPostProcessor接口的postProcessAfterInitialization()
7、销毁
如果一个 Bean 同时使用了多种销毁钩子,它们的执行顺序是:
使用
@PreDestroy注解的方法 实现DisposableBean接口的destroy()方法 自定义配置的销毁方法(通过 XML 或@Bean注解)
4、springmvc收到一个请求后的执行流程
- 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")] // 方法参数信息
DispatcherServlet接收到请求,询问所有的handlerMapping实现类,谁能处理,找到RequestMappingHandlerMapping,将该接口的拦截器(intercetor)和方法信息构建成HandlerExecutionChain打包返回DispatcherServlet拿到HandlerExecutionChain后,开始找能执行它的HandlerAdapter。寻找适配器:RequestMappingHandlerAdapter说:“我能执行这种@RequestMapping的方法”。RequestMappingHandlerAdapter找到参数处理器,比如@RequestParam的处理器进行参数解析。- 通过反射的方式执行
// 伪代码,体现 HandlerAdapter 内部的逻辑
Object[] args = new Object[]{"abc"}; // 解析得到的参数值
HandlerMethod handlerMethod = ...; // 之前找到的“说明书”
// 最关键的一行:通过反射调用目标方法
Object returnValue = handlerMethod.getMethod().invoke(
handlerMethod.getBean(), // 你的Controller对象(从IOC容器来的)
args // 参数值数组
);
5.返回结果