从 getFactory 方法的源码可以看出,其核心逻辑分为 4 步:
- 首先,尝试查找全局属性org.apache.commons.logging.LogFactory,如果指定了具体类,尝试创建实例 。
- 利用 Java SPI 机制,尝试在 classpatch 的 META-INF/services 目录下寻找org.apache.commons.logging.LogFactory 的实现类 。
- 尝试从 classpath 目录下的 commons-logging.properties 文件中查找org.apache.commons.logging.LogFactory 属性,如果指定了具体类,尝试创建实例 。
- 以上情况如果都不满足,则实例化默认实现类,即org.apache.commons.logging.impl.LogFactoryImpl 。
下面是一个 Spring Boot 入口示例,可以看到,代码非常简洁 。
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;@SpringBootApplication@RestControllerpublic class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}@GetMapping("/hello")public String hello(@RequestParam(value = "https://www.huyubaike.com/biancheng/name", defaultValue = "https://www.huyubaike.com/biancheng/World") String name) {return String.format("Hello %s!", name);}}那么,Spring Boot 是如何做到寥寥几行代码,就可以运行一个 Spring Boot 应用的呢 。我们不妨带着疑问,从源码入手,一步步探究其原理 。
4.3.1 @SpringBootApplication 注解首先,Spring Boot 应用的启动类上都会标记一个
@SpringBootApplication 注解 。
@SpringBootApplication 注解定义如下:
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan(excludeFilters = {@Filter(type = FilterType.CUSTOM,classes = {TypeExcludeFilter.class}), @Filter(type = FilterType.CUSTOM,classes = {AutoConfigurationExcludeFilter.class})})public @interface SpringBootApplication {// 略}除了 @Target、 @Retention、@Documented、@Inherited 这几个元注解, @SpringBootApplication 注解的定义中还标记了 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan 三个注解 。
4.3.2 @SpringBootConfiguration 注解从@SpringBootConfiguration 注解的定义来看,@SpringBootConfiguration 注解本质上就是一个 @Configuration 注解,这意味着被@SpringBootConfiguration 注解修饰的类会被 Spring Boot 识别为一个配置类 。
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Configurationpublic @interface SpringBootConfiguration {@AliasFor(annotation = Configuration.class)boolean proxyBeanMethods() default true;}4.3.3 @EnableAutoConfiguration 注解@EnableAutoConfiguration 注解定义如下:
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import({AutoConfigurationImportSelector.class})public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class<?>[] exclude() default {};String[] excludeName() default {};}@EnableAutoConfiguration 注解包含了 @AutoConfigurationPackage与 @Import({AutoConfigurationImportSelector.class}) 两个注解 。
4.3.4 @AutoConfigurationPackage 注解@AutoConfigurationPackage 会将被修饰的类作为主配置类,该类所在的 package 会被视为根路径,Spring Boot 默认会自动扫描根路径下的所有 Spring Bean(被 @Component 以及继承 @Component 的各个注解所修饰的类) 。——这就是为什么 Spring Boot 的启动类一般要置于根路径的原因 。这个功能等同于在 Spring xml 配置中通过 context:component-scan 来指定扫描路径 。@Import 注解的作用是向 Spring 容器中直接注入指定组件 。@AutoConfigurationPackage 注解中注明了@Import({Registrar.class}) 。Registrar 类用于保存 Spring Boot 的入口类、根路径等信息 。
经验总结扩展阅读
- 10月28日3时42分新疆阿克苏地区沙雅县发生3.0级地震
- 10月28日4时34分新疆阿克苏地区温宿县发生3.0级地震
- 今年第22号台风“尼格”最强可达台风级 30日傍晚前后进入南海海面
- 红米note9pro评测最新_红米note9pro深度测评
- 空调一级能效与三级能效的区别是什么
- iOS 16.3.1正式版续航怎么样 iOS 16.3.1升级建议
- ipx7和ip68哪个更防水 哪个防水等级更高
- 10月28日今起三天陕西持续阴雨模式局地阵风6级 风寒效应明显需保暖
- EasyPoi大数据导入导出百万级实例
- Dubbo-聊聊通信模块设计