深入理解 HttpSecurity( 二 )

这里的方法比较简单:

  1. getConfigurer 获取一个配置对象 。Spring Security 过滤器链中的所有过滤器对象都是由 xxxConfigure 来进行配置的,这里就是获取这个 xxxConfigure 对象 。
  2. removeConfigurer 移除一个配置对象 。
  3. setSharedObject/getSharedObject 配置/获取由多个 SecurityConfigurer 共享的对象 。
  4. authenticationProvider 方法表示配置验证器 。
  5. userDetailsService 配置数据源接口 。
  6. addFilterAfter 在某一个过滤器之前添加过滤器 。
  7. addFilterBefore 在某一个过滤器之后添加过滤器 。
  8. addFilter 添加一个过滤器,该过滤器必须是现有过滤器链中某一个过滤器或者其扩展 。
这便是 HttpSecurityBuilder 中的功能,这些接口在 HttpSecurity 中都将得到实现 。
1.4 AbstractSecurityBuilderAbstractSecurityBuilder 类实现了 SecurityBuilder 接口,该类中主要做了一件事,就是确保整个构建只被构建一次 。
public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> { private AtomicBoolean building = new AtomicBoolean(); private O object; public final O build() throws Exception {  if (this.building.compareAndSet(false, true)) {   this.object = doBuild();   return this.object;  }  throw new AlreadyBuiltException("This object has already been built"); } public final O getObject() {  if (!this.building.get()) {   throw new IllegalStateException("This object has not been built");  }  return this.object; } protected abstract O doBuild() throws Exception;}可以看到,这里重新定义了 build 方法,并设置 build 方法为 final 类型,无法被重写,在 build 方法中,通过 AtomicBoolean 实现该方法只被调用一次 。具体的构建逻辑则定义了新的抽象方法 doBuild,将来在实现类中通过 doBuild 方法定义构建逻辑 。
1.5 AbstractConfiguredSecurityBuilderAbstractSecurityBuilder 方法的实现类就是 AbstractConfiguredSecurityBuilder 。
AbstractConfiguredSecurityBuilder 中所做的事情就比较多了,我们分别来看 。
首先 AbstractConfiguredSecurityBuilder 中定义了一个枚举类,将整个构建过程分为 5 种状态,也可以理解为构建过程生命周期的五个阶段,如下:
private enum BuildState { UNBUILT(0), INITIALIZING(1), CONFIGURING(2), BUILDING(3), BUILT(4); private final int order; BuildState(int order) {  this.order = order; } public boolean isInitializing() {  return INITIALIZING.order == order; } public boolean isConfigured() {  return order >= CONFIGURING.order; }}五种状态分别是 UNBUILT、INITIALIZING、CONFIGURING、BUILDING 以及 BUILT 。另外还提供了两个判断方法,isInitializing 判断是否正在初始化,isConfigured 表示是否已经配置完毕 。
AbstractConfiguredSecurityBuilder 中的方法比较多,松哥在这里列出来两个关键的方法和大家分析:
private <C extends SecurityConfigurer<O, B>> void add(C configurer) { Assert.notNull(configurer, "configurer cannot be null"); Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer   .getClass(); synchronized (configurers) {  if (buildState.isConfigured()) {   throw new IllegalStateException("Cannot Apply " + configurer     + " to already built object");  }  List<SecurityConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.configurers    .get(clazz) : null;  if (configs == null) {   configs = new ArrayList<>(1);  }  configs.add(configurer);  this.configurers.put(clazz, configs);  if (buildState.isInitializing()) {   this.configurersAddedInInitializing.add(configurer);  } }}private Collection<SecurityConfigurer<O, B>> getConfigurers() { List<SecurityConfigurer<O, B>> result = new ArrayList<>(); for (List<SecurityConfigurer<O, B>> configs : this.configurers.values()) {  result.addAll(configs); } return result;}


推荐阅读