解析源码---结合@ServletComponentScan与@WebServlet,@WebFilter,@WebListener注册servlet,filter,listener

概述

由于@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());
   }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章