深入理解 HttpSecurity( 三 )

第一个就是这个 add 方法,这相当于是在收集所有的配置类 。将所有的 xxxConfigure 收集起来存储到 configurers 中,将来再统一初始化并配置,configurers 本身是一个 LinkedHashMap,key 是配置类的 class,value 是一个集合,集合里边放着 xxxConfigure 配置类 。当需要对这些配置类进行集中配置的时候,会通过 getConfigurers 方法获取配置类,这个获取过程就是把 LinkedHashMap 中的 value 拿出来,放到一个集合中返回 。
另一个方法就是 doBuild 方法 。
@Overrideprotected final O doBuild() throws Exception { synchronized (configurers) {  buildState = BuildState.INITIALIZING;  beforeInit();  init();  buildState = BuildState.CONFIGURING;  beforeConfigure();  configure();  buildState = BuildState.BUILDING;  O result = performBuild();  buildState = BuildState.BUILT;  return result; }}private void init() throws Exception { Collection<SecurityConfigurer<O, B>> configurers = getConfigurers(); for (SecurityConfigurer<O, B> configurer : configurers) {  configurer.init((B) this); } for (SecurityConfigurer<O, B> configurer : configurersAddedInInitializing) {  configurer.init((B) this); }}private void configure() throws Exception { Collection<SecurityConfigurer<O, B>> configurers = getConfigurers(); for (SecurityConfigurer<O, B> configurer : configurers) {  configurer.configure((B) this); }}在 AbstractSecurityBuilder 类中,过滤器的构建被转移到 doBuild 方法上面了,不过在 AbstractSecurityBuilder 中只是定义了抽象的 doBuild 方法,具体的实现在 AbstractConfiguredSecurityBuilder 。
doBuild 方法就是一边更新状态,进行进行初始化 。
beforeInit 是一个预留方法,没有任何实现 。
init 方法就是找到所有的 xxxConfigure,挨个调用其 init 方法进行初始化 。
beforeConfigure 是一个预留方法,没有任何实现 。
configure 方法就是找到所有的 xxxConfigure,挨个调用其 configure 方法进行配置 。
最后则是 performBuild 方法,是真正的过滤器链构建方法,但是在 AbstractConfiguredSecurityBuilder 中 performBuild 方法只是一个抽象方法,具体的实现在 HttpSecurity 中 。
这便是 HttpSecurity 所有父类、父接口的功能 。
看完了父辈,接下来回到我们今天文章的主题,HttpSecurity 。
2. HttpSecurityHttpSecurity 做的事情,就是进行各种各样的 xxxConfigurer 配置 。
随便举几例:
public CorsConfigurer<HttpSecurity> cors() throws Exception { return getOrApply(new CorsConfigurer<>());}public CsrfConfigurer<HttpSecurity> csrf() throws Exception { ApplicationContext context = getContext(); return getOrApply(new CsrfConfigurer<>(context));}public ExceptionHandlingConfigurer<HttpSecurity> exceptionHandling() throws Exception { return getOrApply(new ExceptionHandlingConfigurer<>());}HttpSecurity 中有大量类似的方法,过滤器链中的过滤器就是这样一个一个配置的 。我就不一一介绍了 。
每个配置方法的结尾都会来一句 getOrApply,这个是干嘛的?
private <C extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>> C getOrApply(  C configurer) throws Exception { C existingConfig = (C) getConfigurer(configurer.getClass()); if (existingConfig != null) {  return existingConfig; } return apply(configurer);}getConfigurer 方法是在它的父类 AbstractConfiguredSecurityBuilder 中定义的,目的就是去查看当前这个 xxxConfigurer 是否已经配置过了 。
如果当前 xxxConfigurer 已经配置过了,则直接返回,否则调用 apply 方法,这个 apply 方法最终会调用到 AbstractConfiguredSecurityBuilder#add 方法,将当前配置 configurer 收集起来 。
HttpSecurity 中还有一个 addFilter 方法:
public HttpSecurity addFilter(Filter filter) { Class<? extends Filter> filterClass = filter.getClass(); if (!comparator.isRegistered(filterClass)) {  throw new IllegalArgumentException(    "The Filter class "      + filterClass.getName()      + " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead."); } this.filters.add(filter); return this;}


推荐阅读