概述
由于@ServletComponentScan所在类被加载BeanDefinition时,会加载其Registar。所以会导入ServletComponentScanRegistrar,由此向beanfactory添加了一个ServletComponentRegisteringPostProcessor。当最后调用各种nonOrderedPostProcessors时,会调用ServletComponentRegisteringPostProcessor的postProcessBeanFactory,最终扫描路径获取由@WebServlet,@WebFilter,@WebListener注册的servlet,filter,listener。
前言
我们可以看见@ServletComponentScan import 了ServletComponentScanRegistrar
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ServletComponentScanRegistrar.class)
public @interface ServletComponentScan {
......
}
而ServletComponentScanRegistrar向beanfactory添加了ServletComponentRegisteringPostProcessor
class ServletComponentScanRegistrar implements ImportBeanDefinitionRegistrar {
......
private void addPostProcessor(BeanDefinitionRegistry registry,
Set<String> packagesToScan) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(ServletComponentRegisteringPostProcessor.class);
beanDefinition.getConstructorArgumentValues()
.addGenericArgumentValue(packagesToScan);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(BEAN_NAME, beanDefinition);
}
......
}
入口
通过@ServletComponentScan所在组件类加载BeanDefinition时,加载ServletComponentScanRegistrar
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
......
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
//加载ServletComponentScanRegistrar
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
然后调用ServletComponentScanRegistrar的registerBeanDefinitions:向BeanDefinitionRegistry添加ServletComponentRegisteringPostProcessor
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
//根据注解所在类的元信息获取扫描包路径,如果没有定义注解扫描的包路径,就以注解所在类的包路径为默认路径
Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
//是否已有ServletComponentRegisteringPostProcessor,无则添加,有则更新
if (registry.containsBeanDefinition(BEAN_NAME)) {
updatePostProcessor(registry, packagesToScan);
}
else {
addPostProcessor(registry, packagesToScan);
}
}
执行
AbstractApplicationContext:其中refresh方法会调用各个后处理器
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
......
// 调用各个后处理器,添加各种beandefinition
invokeBeanFactoryPostProcessors(beanFactory);
......
}
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors:
统一处理各种BeanFactoryPostProcessor,最后一种BeanFactoryPostProcessor处理就是有关ServletComponentRegisteringPostProcessor处理servlet,filter,listener
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
......
//添加各类bean
}
......
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
//调用ServletComponentRegisteringPostProcessor处理servlet,filter,listener
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
......
}
ServletComponentRegisteringPostProcessor
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
//必须是嵌入式的tomcat并且此时ServletContext为null
if (isRunningInEmbeddedWebServer()) {
//获取环境和ResourceLoader,及确定需要扫描@WebServlet,@WebFilter,@WebListener
ClassPathScanningCandidateComponentProvider componentProvider = createComponentProvider();
//packagesToScan是@ServletComponentScan的扫描路径
for (String packageToScan : this.packagesToScan) {
scanPackage(componentProvider, packageToScan);
}
}
}
private void scanPackage(
ClassPathScanningCandidateComponentProvider componentProvider,
String packageToScan) {
//获取包路径下有@WebServlet,@WebFilter,@WebListener的类
for (BeanDefinition candidate : componentProvider
.findCandidateComponents(packageToScan)) {
if (candidate instanceof ScannedGenericBeanDefinition) {
for (ServletComponentHandler handler : HANDLERS) {
handler.handle(((ScannedGenericBeanDefinition) candidate),
(BeanDefinitionRegistry) this.applicationContext);
}
}
}
}
WebServletHandler.doHandle:最终添加Servlet的BeanDefinition
@Override
public void doHandle(Map<String, Object> attributes,
ScannedGenericBeanDefinition beanDefinition,
BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.rootBeanDefinition(ServletRegistrationBean.class);
builder.addPropertyValue("asyncSupported", attributes.get("asyncSupported"));
builder.addPropertyValue("initParameters", extractInitParameters(attributes));
builder.addPropertyValue("loadOnStartup", attributes.get("loadOnStartup"));
String name = determineName(attributes, beanDefinition);
builder.addPropertyValue("name", name);
builder.addPropertyValue("servlet", beanDefinition);
builder.addPropertyValue("urlMappings", extractUrlPatterns(attributes));
builder.addPropertyValue("multipartConfig",
determineMultipartConfig(beanDefinition));
//注册BeanDefinition
registry.registerBeanDefinition(name, builder.getBeanDefinition());
}
WebFilterHandler:最终添加合法的filter的BeanDefinition
@Override
public void doHandle(Map<String, Object> attributes,
ScannedGenericBeanDefinition beanDefinition,
BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.rootBeanDefinition(FilterRegistrationBean.class);
builder.addPropertyValue("asyncSupported", attributes.get("asyncSupported"));
builder.addPropertyValue("dispatcherTypes", extractDispatcherTypes(attributes));
builder.addPropertyValue("filter", beanDefinition);
builder.addPropertyValue("initParameters", extractInitParameters(attributes));
String name = determineName(attributes, beanDefinition);
builder.addPropertyValue("name", name);
builder.addPropertyValue("servletNames", attributes.get("servletNames"));
builder.addPropertyValue("urlPatterns", extractUrlPatterns(attributes));
//注册BeanDefinition
registry.registerBeanDefinition(name, builder.getBeanDefinition());
}
对于Listener处理差不多,通过WebListenerHandler.doHandle()
@Override
protected void doHandle(Map<String, Object> attributes,
ScannedGenericBeanDefinition beanDefinition,
BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.rootBeanDefinition(ServletListenerRegistrationBean.class);
builder.addPropertyValue("listener", beanDefinition);
//注册BeanDefinition
registry.registerBeanDefinition(beanDefinition.getBeanClassName(),
builder.getBeanDefinition());
}