Spring Boot 之 Filter顺序配置 @Order无效原因解读(源码理解)

写在前面

  • ApplicationContext 实现: AnnotationConfigEmbeddedWebApplicationContext
  • BeanFactory实现: DefaultListableBeanFactory

Spring Boot Filter类结构图

implements
implements
extends
extends
CompositeFilter
Filter
GenericFilterBean
DelegatingFilterProxy
OncePerRequestFilter
extends
extends
extends
extends
extends
extends
CharacterEncodingFilter
OncePerRequestFilter
HiddenHttpMethodFilter
HttpPutFormContentFilter
RequestContextFilter
ShallowEtagHeaderFilter
AbstractRequestLoggingFilter
extends
extends
extends
CommonsRequestLoggingFilter
AbstractRequestLoggingFilter
Log4jNestedDiagnosticContextFilter
ServletContextRequestLoggingFilter

对应Spring的Filter讲解:
https://blog.csdn.net/geloin/article/details/7441330

Spring Boot 自带初始化的Filter

[INFO] 2019-01-23 15:42:23  org.springframework.boot.web.servlet.FilterRegistrationBean 258 - Mapping filter: 'characterEncodingFilter' to: [/*]
[INFO] 2019-01-23 15:42:23  org.springframework.boot.web.servlet.FilterRegistrationBean 258 - Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
[INFO] 2019-01-23 15:42:23  org.springframework.boot.web.servlet.FilterRegistrationBean 258 - Mapping filter: 'httpPutFormContentFilter' to: [/*]
[INFO] 2019-01-23 15:42:23  org.springframework.boot.web.servlet.FilterRegistrationBean 258 - Mapping filter: 'requestContextFilter' to: [/*]
  • CharacterEncodingFilter :编码过滤器
public class OrderedCharacterEncodingFilter extends CharacterEncodingFilter
		implements Ordered {
	private int order = Ordered.HIGHEST_PRECEDENCE;//-2147483648
	// 其余此处省略
}
  • HiddenHttpMethodFilter :处理隐藏的PUT,DELETE等请求方法
public class OrderedHiddenHttpMethodFilter extends HiddenHttpMethodFilter
		implements Ordered {
	public static final int DEFAULT_ORDER = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER - 10000;
	private int order = DEFAULT_ORDER; //-10000
	// 其余此处省略
}
  • HttpPutFormContentFilter :处理PUT表单请求
public class OrderedHttpPutFormContentFilter 
        extends HttpPutFormContentFilter implements Ordered {
	public static final int DEFAULT_ORDER = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER - 9900;
	private int order = DEFAULT_ORDER; //-9900
	// 其余此处省略
}
  • RequestContextFilter :设置请求的上下文环境
public class OrderedRequestContextFilter extends RequestContextFilter             implements Ordered {
	// Order defaults to after Spring Session filter
	private int order = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER - 105;//-105

	// 其余此处省略
}
  • 在上述Spring Boot 自带Filter的顺序由 order 从小到大排序;

  • 综合上述,可以试图将自定义的filter也由这种方式来定义其顺序

    • 经过验证,即使使用@Order注解还是实现Ordered接口,都无法实现自定义顺序
@WebFilter(urlPatterns = "/*")
@Order(-9901)
public class FirstFilter extends OncePerRequestFilter implements Ordered {

    private static final Logger logger = LoggerFactory.getLogger(FirstFilter.class);
    private int order = -110;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        logger.info("FirstFilter:doFilterInternal");
        filterChain.doFilter(request, response);
    }

    @Override
    public int getOrder() {
        return order;
    }
}
  • 从Spring Boot初始化源码进行解读上述方式为什么自定义filter无法实现
public class SpringApplication {
    public ConfigurableApplicationContext run(String... args) {
		... 此处省略若干源码
			refreshContext(context);
		... 此处省略若干源码			
	}
	private void refreshContext(ConfigurableApplicationContext context) {
		refresh(context);
		... 此处省略若干源码		
	}
	protected void refresh(ApplicationContext applicationContext) {
		Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
		((AbstractApplicationContext) applicationContext).refresh();
	}
}
    • 由上源码得知调用了AbstractApplicationContext.refresh(),但是由于多态,实际调用则是
      AnnotationConfigEmbeddedWebApplicationContext重写的refresh()方法
public class AnnotationConfigEmbeddedWebApplicationContext
		extends EmbeddedWebApplicationContext {
}

public class EmbeddedWebApplicationContext extends 
        GenericWebApplicationContext {
	@Override
	public final void refresh() throws BeansException, IllegalStateException {
		... 此处省略若干源码
			super.refresh(); // 此处调用父类AbstractApplicationContext.refresh()
		... 此处省略若干源码
	}
}
public class GenericWebApplicationContext extends GenericApplicationContext
		implements ConfigurableWebApplicationContext, ThemeSource {}
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {}

public abstract class AbstractApplicationContext extends 
        DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean {
	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			... 此处省略若干源码
			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);// WebFilter都在此时进行实例化

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}
			... 此处省略若干源码
		}
	}
	/**
	 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
	 * respecting explicit order if given.
	 * <p>Must be called before singleton instantiation.
	 */
	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
		... 此处省略若干源码
	}
}
    • 委任PostProcessorRegistrationDelegate处理BeanFactoryPostProcessors ,从此处可得知,注册Filter的顺序是由类名的顺序决定的。
class PostProcessorRegistrationDelegate {
public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
... 此处省略若干源码
		// Finally, invoke all other BeanFactoryPostProcessors.
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
		... 此处省略若干源码
	}
	
	/**
	 * Invoke the given BeanFactoryPostProcessor beans.
	 */
	private static void invokeBeanFactoryPostProcessors(
			Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
		for (BeanFactoryPostProcessor postProcessor : postProcessors) {
			// 处理@WebFilter的postProcessor 为ServletComponentRegisteringPostProcessor
			postProcessor.postProcessBeanFactory(beanFactory);
		}
	}
}

//  File:org.springframework.boot.web.servlet.ServletComponentRegisteringPostProcessor;
class ServletComponentRegisteringPostProcessor
		implements BeanFactoryPostProcessor, ApplicationContextAware {

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
			throws BeansException {
		if (isRunningInEmbeddedContainer()) {
			ClassPathScanningCandidateComponentProvider componentProvider = createComponentProvider();
			for (String packageToScan : this.packagesToScan) {
				scanPackage(componentProvider, packageToScan);
			}
		}
	}

	private void scanPackage(
			ClassPathScanningCandidateComponentProvider componentProvider,
			String packageToScan) {
			// packageToScan得到的FilterBeanDefinition顺序由包名决定
		for (BeanDefinition candidate : componentProvider
				.findCandidateComponents(packageToScan)) {
			if (candidate instanceof ScannedGenericBeanDefinition) {
				for (ServletComponentHandler handler : HANDLERS) {
					// 由WebFilterHandler处理FilterBeanDefinition,并注册Filter
					handler.handle(((ScannedGenericBeanDefinition) candidate),
							(BeanDefinitionRegistry) this.applicationContext);
				}
			}
		}
	}
	... 此处省略若干源码
}
    • 重点在ServletComponentHandler 处理带有注解WebFilter的类;handle方法中处理的attributes是@WebFilter的属性,因为@WebFilter本身是没有Order属性,所以构建的Filter将是默认的Order值,而上面源码可得知,类名可决定注册Filter的顺序(即Filter过滤顺序,因为此处只能注册默认的Order值)
abstract class ServletComponentHandler {
	... 此处省略若干源码
	void handle(ScannedGenericBeanDefinition beanDefinition,
			BeanDefinitionRegistry registry) {
		// 此处可以看出,attributes是通过@WebFilter的属性来获得
		Map<String, Object> attributes = beanDefinition.getMetadata()
				.getAnnotationAttributes(this.annotationType.getName());
		if (attributes != null) {
			// 此处调用的为模板方法(WebFilterHandler的实现)
			doHandle(attributes, beanDefinition, registry);
		}
	}
	protected abstract void doHandle(Map<String, Object> attributes,
			ScannedGenericBeanDefinition beanDefinition, BeanDefinitionRegistry registry);
}

class WebFilterHandler extends ServletComponentHandler {
	@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("urlPatterns", attributes));
		registry.registerBeanDefinition(name, builder.getBeanDefinition());
	}
	... 此处省略若干源码
}

写在最后

  • 开篇给出Spring Boot 自带的4中Filter,主要为了了解其过滤顺序,且与自定义Filter的执行顺序。(由Order值从小到大的顺序),由Filter类名来实现自定义Filter顺序,因Order为默认值,所以自带的4种Filter都会比自定义的Filter先执行。
  • 也可以使用FilterRegistrationBean 来设置Order定义过滤器顺序。

转一篇 FilterRegistrationBean 设置过滤器顺序文章: https://blog.csdn.net/qq_34531925/article/details/78194651

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值