目录
ServletComponentScanRegistrar类
ServletComponentRegisteringPostProcessor
ServletContextInitializerBeans
SpringBoot版本:2.1.1
注解方式
@ServletComponentScan注解
先了解下@ServletComponentScan注解。
@Import注解导入了一个类:ServletComponentScanRegistrar
三个属性,也就是两个属性:
basePackages:String数组,指定要扫描的包
basePackageClasses:Class数组,指定扫描该类所在的包
如果没有指定要扫描的包,则扫描主类所在的包,即@SpringBootApplication注解所在类的包。
ServletComponentScanRegistrar类
该类主要作用是确定要扫描的包,并注册一个BeanFactoryPostProcessor,用于扫描@WebServlet、@WebFilter和@WebListener注解,自动注册成bean。
class ServletComponentScanRegistrar implements ImportBeanDefinitionRegistrar {
private static final String BEAN_NAME = "servletComponentRegisteringPostProcessor";
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
//得到注解中指定的包,如果没有则扫描主类所在的包
Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
//判断bean工厂中是否存在servletComponentRegisteringPostProcessor的bean定义
if (registry.containsBeanDefinition(BEAN_NAME)) {
//存在的话直接从servletComponentRegisteringPostProcessor的构造参数中得到要扫描的包,加上从注解中得到的指定包
updatePostProcessor(registry, packagesToScan);
}
else {
//不存在就注册一个
addPostProcessor(registry, packagesToScan);
}
}
private void updatePostProcessor(BeanDefinitionRegistry registry,
Set<String> packagesToScan) {
//得到bean定义
BeanDefinition definition = registry.getBeanDefinition(BEAN_NAME);
//得到构造函数中类型配置的参数
ValueHolder constructorArguments = definition.getConstructorArgumentValues()
.getGenericArgumentValue(Set.class);
@SuppressWarnings("unchecked")
//得到值
Set<String> mergedPackages = (Set<String>) constructorArguments.getValue();
//加上注解中设置包
mergedPackages.addAll(packagesToScan);
constructorArguments.setValue(mergedPackages);
}
private void addPostProcessor(BeanDefinitionRegistry registry,
Set<String> packagesToScan) {
//