前言
我们在阅读Spring(SpringBoot)源码的时候,有可能会被一下前置知识点卡住,影响继续阅读的动力。根据我对Spring的理解,整理一些实用的技巧,减少大家的阅读障碍。如果有什么不正确的地方欢迎大家指正、补充
BeanDefinition
BeanDefinition 是 Bean 的建模对象,如果 BeanFactory 向 Spring 中注册了一个BeanDefinition,Spring在接下来的流程中将会实例化一个Bean。BeanDefinition的属性很多,各有不同的作用,其中与实例化相关的属性有:
- beanClass
- instanceSupplier
- factoryBeanName
- factoryMethodName
不考虑用户手动注册的情况,通过一些值能推断出它是如何解析而成:
- factoryBeanName、factoryMethodName不为 null:@Configuration + @Bean 解析而成,默认情况下,factoryBeanName 为 @Configuration 标记的类的类名的驼峰形式,factoryMethodName为 @Bean 标记的方法的方法名
- instanceSupplier不为null : 一般为相关源码的手动设置
- 上述属性都为null,beanClass不为null:类上存在 @Component 注解,被扫描解析而成
BeanDefinition其他属性的作用,可移步相关博文 : Spring之BeanDefinition
@Import注解
注入的类一般继承 ImportSelector 或者 ImportBeanDefinitionRegistrar 接口
- 继承ImportSelector接口:会在解析阶段执行 selectImports 方法,方法返回的类名数组,会被解析成 BeanDefinition 对象,即后期会被实例化成Bean
- 继承ImportBeanDefinitionRegistrar接口:会在解析阶段执行 registerBeanDefinitions 方法,一般会注册 BeanDefinition 对象
- 配置类
比如说 @EnableXxx 这样的注解,其源码上一般会存在 @Import 注解,通过 selectImports 或者 registerBeanDefinitions 方法,注册一个或者多个 BeanDefinition 对象,一般情况下会有一个BeanDefinition 的 beanClass 为 BeanPostProcessor 的子类,这样就存在一个具有特定功能的BeanPostProcessor,可以对具有指定特征的Bean进行增强。
如果@EnableXxx注解,使用的是 selectImports 方法注册BeanDefinition,如果希望获取注解设置的属性,相关类可以继承 ImportAware 接口,通过 setImportMetadata 方法,获取注解相关属性,相关博文 : @Import在Spring中的应用之@EnableAsync
@EnableConfigurationProperties
如果 @EnableConfigurationProperties 注解指定value,即向Spring容器中注册BeanDefinition,我们举个例子来演示现象.
@Configuration
@EnableConfigurationProperties({FirstProperties.class, SecondProperties.class})
public class AppConfig {
}
@ConfigurationProperties
public class FirstProperties {
}
@ConfigurationProperties
public class SecondProperties {
}
我们可以看到FirstProperties、SecondProperties所属Class上并没有@Component相关注解,但是Spring容器中存在相关类型的Bean,这就是@EnableConfigurationProperties注解发挥的作用,有兴趣的小伙伴也可以用上文中 @Import 注解的作用来分析@EnableConfigurationProperties注解是如何发挥作用的。相关博文: @EnableConfigurationProperties源码解析
构造方法
如果一个类,有且仅有一个有参构造方法,Spring会选择以此构造方法实例化对象,并且会根据参数类型和参数名,从Spring中查找相关依赖。使用有参构造方法实例化对象,是一种隐式的依赖注入,未查找到相关依赖,可能会抛出异常。举例演示如下:
@Component
public class A {
private B b;
public A(B b) {
this.b = b;
}
}
public class B {
}
如果B未被Spring纳入管理,则会抛出异常。
解决方案1 : 不存在就不注入
@Component
public class A {
private B b;
public A(ObjectProvider<B> b) {
this.b = b.getIfAvailable();
}
}
解决方案2 : 将B纳入Spring管理
@Component
public class B {
}
配置类有且仅有一个有参构造方法在SpringBoot中的运用
WebMvcAutoConfigurationAdapter相关源码
这个类就同时用到@EnableConfigurationProperties注解和唯一有参构造方法相关知识。
通过YAML(YML)文件查看相关配置
比如说 YAML 文件有以下配置:
如果我们希望查看相关配置的默认值,可以通过 Edit -> Find -> Find in Files -> spring.web
选择带有 @ConfigurationProperties 注解的Class文件,相关配置的默认值都在这个类中