springboot 2.1.3.RELEASE添加filter,servlet源码学习

Servlet规范中,通过ServeltContext来注册Filter、Servlet,这里分析Filter,Servlet是相同逻辑

springboot2.0中,我们通过

FilterRegistrationBean将指定得filter来实现ServeltContext注册filter

FilterRegistrationBean的实例化过程

public FilterRegistrationBean(T filter, ServletRegistrationBean... servletRegistrationBeans) {
        super(servletRegistrationBeans);
        Assert.notNull(filter, "Filter must not be null");
        this.filter = filter;
}

super的实例化
AbstractFilterRegistrationBean(ServletRegistrationBean... servletRegistrationBeans) {
        Assert.notNull(servletRegistrationBeans, "ServletRegistrationBeans must not be null");
        Collections.addAll(this.servletRegistrationBeans, servletRegistrationBeans);
}

可知FilterRegistrationBean得实例化过程就是将Filter保存到servletRegistrationBeans(一个set)中

再分析FilterRegistrationBean类

FilterRegistrationBean的父类是一个ServletContextInitializer,他有一个方法onStartup(ServletContext servletContext)
其结果最终会调用
servletContext.addFilter(this.getOrDeduceName(filter), filter)
现在看看ServletContextInitializer.onStartup的调用地方
springboot启动
new SpringApplication(XXApplication.class).run(XXApplication.class,args)
调用
refreshContext(context); -> refresh(context); -> ((AbstractApplicationContext) applicationContext).refresh();
-> ServletWebServerApplicationContext.onRefresh(); -> createWebServer();

WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
	ServletWebServerFactory factory = getWebServerFactory();
	this.webServer = factory.getWebServer(getSelfInitializer());
}

再分析getSelfInitializer方法

prepareWebApplicationContext(servletContext);
		registerApplicationScope(servletContext);
		WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(),servletContext);
		for (ServletContextInitializer beans :getServletContextInitializerBeans()) {
              //调用ServletContextInitializer的onStartup方法
              beans.onStartup(servletContext); 
}
-> getServletContextInitializerBeans()
-> new ServletContextInitializerBeans(getBeanFactory())
-> addAdaptableBeans(beanFactory)

 

addAdaptableBeans(ListableBeanFactory beanFactory) 代码如下:
MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory);
//将servlet类的bean包装为ServletRegistrationBean
addAsRegistrationBean(beanFactory, Servlet.class,new ServletRegistrationBeanAdapter(multipartConfig));
//将Filter的bean包装为FilterRegistrationBean
addAsRegistrationBean(beanFactory, Filter.class,new FilterRegistrationBeanAdapter());
for (Class<?> listenerType : ServletListenerRegistrationBean.getSupportedTypes()) {		
  addAsRegistrationBean(beanFactory, EventListener.class,(Class<EventListener>) listenerType,new ServletListenerRegistrationBeanAdapter()); }

 这里提一下,如果Servlet的bean实例名为dispatcherServlet,且该实例在seen集合中(seen集合为自定义配置的实例,通过ServletContextInitializerBeans.addServletContextInitializerBean入口可以查看源码),则设置默认值为  /

String url = (totalNumberOfSourceBeans != 1) ? "/" + name + "/" : "/";
if (name.equals(DISPATCHER_SERVLET_NAME)) {
	url = "/"; // always map the main dispatcherServlet to "/"
}
ServletRegistrationBean<Servlet> bean = new ServletRegistrationBean<>(source,url);	
bean.setName(name); bean.setMultipartConfig(this.multipartConfig); return bean;

 

总结:springboot启动时,会将所有的 FilterRegistrationBean、ServletRegistrationBean以及被spring管理的Servlet和Filter的实例,通过ServletContext注册Servlet以及Filter

如果不希望filter自动注册,可以通过以下方式:

 @Bean
    public FilterRegistrationBean registration(@Qualifier("loginFilter") LoginFilter loginFilter) {
        FilterRegistrationBean registration = new FilterRegistrationBean(loginFilter);
        registration.setEnabled(false);
        return registration;
    }

 

 

 

原文地址:https://www.cnblogs.com/jaxlove-it/p/10564683.html