Build设计模式

配置模块化

用build设计模式将配置模块化。

配置的依赖关系管理

主从模式

可以暂时先看下面的主从从模式。

单属性配置

httpSecurity.authorizeRequests().regexMatchers("/url/**").authenticated().regexMatchers("/url2/**").anonymous();

上边的代码authorizeRequests方法返回的是一个ExpressionUrlAuthorizationConfigurer对象,regexMatchers方法返回一个AuthorizedUrl对象,这个对象有很多设置权限的方法,但是这个对象的所有方法能且只能被调用一次。Spring Security用来控制只能被调用一次的方法就是不管调用AuthorizedUrl对象的哪个方法,接着返回ExpressionUrlAuthorizationConfigurer对象。

主从从模式

httpSecurity.sessionManagement().maximumSessions(10).expiredUrl("someurl").and().sessionFixation();

上边的代码分解如下:

SessionManagementConfigurer<HttpSecurity> sessionManagementConfigurer = httpSecurity.sessionManagement();
ConcurrencyControlConfigurer concurrencyControlConfigurer = sessionManagementConfigurer.maximumSessions(10);
concurrencyControlConfigurer = concurrencyControlConfigurer.expiredUrl("someurl");
sessionManagementConfigurer = concurrencyControlConfigurer.and();
sessionManagementConfigurer.sessionFixation();

要有从任何一个子模块回到上一个模块的方式。

使用泛型配置配置的依赖关系

正确使用泛型,可以让一个子模块同时配置到多个类似的父模块。

<http>
<cors configuration-source-ref="test" ref="test"/>
</http>
<cors configuration-source-ref="test" ref="test"/>

如上,cors这个配置可以同时存在于两个不同的父元素中。
Spring Security中使用了大量的泛型很好的处理了这个问题。

public class CorsConfigurer<H extends HttpSecurityBuilder<H>>
extends AbstractHttpConfigurer<CorsConfigurer<H>, H>
public abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T, B>, B extends HttpSecurityBuilder<B>>
extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, B>
public abstract class SecurityConfigurerAdapter<O, B extends SecurityBuilder<O>>
implements SecurityConfigurer<O, B>

build方法的正确姿势(init,configure)

特定位置预留扩展点,同时提供构建状态的信息。

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");
}
protected 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;
}
}

运行时信息

可以直接看Spring Security之Builder sharedObjects这篇文章。

与框架或者中间件的非配置模块交互的正确姿势

//TODO

提供一个配置适配器供用户继承重载

类似Spring Security的WebSecurityConfigurerAdapter,在里面提供的内容如下:

  1. 各个配置项的默认配置
  2. 顶级配置项的配置重载回调方法
  3. 重要配置项的配置方法,比如各种顶级概念的bean