spring-security原理与应用系列:建造者
目录
1.构建过程
AbstractSecurityBuilder
AbstractConfiguredSecurityBuilder
WebSecurity
2.建造者类图
SecurityBuilder
AbstractSecurityBuilder
AbstractConfiguredSecurityBuilder
WebSecurity
3.小结
紧接上一篇文章,这一篇我们来看看构建者WebSecurity是如何构建出一个过滤器对象springSecurityFilterChain的。
1.构建过程
点击类WebSecurityConfiguration的方法springSecurityFilterChain()里的this.webSecurity.build(),如下所示:
AbstractSecurityBuilder
public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {
... ...
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");
}
在这里,build()方法调用了doBuild()方法。
点击doBuild()方法,如下所示:
AbstractConfiguredSecurityBuilder
@Override
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;
}
}
在这里,定义了构建对象的所有步骤。包括beforeInit、init、beforeConfigure、configure、performBuild的5个步骤。
点击最后一步performBuild,如下所示:
WebSecurity
public final class WebSecurity extends
AbstractConfiguredSecurityBuilder<Filter, WebSecurity> implements
SecurityBuilder<Filter>, ApplicationContextAware {... ...
@Override
protected Filter performBuild() throws Exception {
int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
List<SecurityFilterChain> securityFilterChains = new ArrayList<SecurityFilterChain>(
chainSize);
for (RequestMatcher ignoredRequest : ignoredRequests) {
securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
}
for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
securityFilterChains.add(securityFilterChainBuilder.build());
}
FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
if (httpFirewall != null) {
filterChainProxy.setFirewall(httpFirewall);
}
filterChainProxy.afterPropertiesSet();
Filter result = filterChainProxy;
if (debugEnabled) {
result = new DebugFilter(filterChainProxy);
}
postBuildAction.run();
return result;
}
在这里,可以看到构建的过滤器类是FilterChainProxy。至于这个类的具体结构,我们后续再进行深入的探究。
我们先看看在系统运行时,这个FilterChainProxy内部都包含有哪些Filter。
设置断点,如下所示:
过滤器代理
在这里,我们看到了FilterChainProxy对象内部包含了很多的Filter。后续再深入了解这些Filter的配置过程及应用场景。
接下来我们重点学习一下与WebSecurity构建者相关的类图模型。
2.建造者类图
在这里,AbstractSecurityBuilder、AbstractConfiguredSecurityBuilder、WebSecurity都是我们在上面一节中有接触过的类。
SecurityBuilder
这个接口是建造者模式的顶级接口,含有建造者对外暴露的构建对象的一个接口方法 build() 。
代码如下:
public interface SecurityBuilder<O> {
O build() throws Exception;
}
AbstractSecurityBuilder
这个类是SecurityBuilder接口的抽象子类,实现了接口的build()方法,为确保构建对象只被构建一次,对父接口方法 build() 进行了原子判断,从而保证每次只构建一次。另外,定义了一个抽象方法 doBuild() 供子类扩展。
代码如下:
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;
}
AbstractConfiguredSecurityBuilder
实现父类的doBuild()方法,这里是真正执行构建的地方。
首先,使用了建造者模式定义了构建对象的所有步骤;
其次,使用了模板方法模式,将构建对象的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
代码如下:
public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>>
extends AbstractSecurityBuilder<O> {
... ...
public <C extends SecurityConfigurer<O, B>> C apply(C configurer) throws Exception {
add(configurer);
return configurer;
}
@SuppressWarnings("unchecked")
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);
}
}
}
@Override
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;
}
}
protected void beforeInit() throws Exception {
}
protected void beforeConfigure() throws Exception {
}
protected abstract O performBuild() throws Exception;
@SuppressWarnings("unchecked")
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);
}
}
@SuppressWarnings("unchecked")
private void configure() throws Exception {
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
for (SecurityConfigurer<O, B> configurer : configurers) {
configurer.configure((B) this);
}
}
}
WebSecurity
实现父类的 performBuild()方法,这是构建对象的所有步骤的最后一个步。通过实现父类方法的方式来定义具体的执行内容。
WebSecurity 的目标是构建 FilterChainProxy 对象,即构建核心过滤器 springSecurityFilterChain。
代码如下:
public final class WebSecurity extends
AbstractConfiguredSecurityBuilder<Filter, WebSecurity> implements
SecurityBuilder<Filter>, ApplicationContextAware {
... ...
@Override
protected Filter performBuild() throws Exception {
int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
List<SecurityFilterChain> securityFilterChains = new ArrayList<>(
chainSize);
for (RequestMatcher ignoredRequest : ignoredRequests) {
securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
}
for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
securityFilterChains.add(securityFilterChainBuilder.build());
}
FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
if (httpFirewall != null) {
filterChainProxy.setFirewall(httpFirewall);
}
filterChainProxy.afterPropertiesSet();
Filter result = filterChainProxy;
postBuildAction.run();
return result;
}
}
3.小结
整个构建过程由beforeInit、init、beforeConfigure、configure、performBuild5大步骤组成。技术层面使用了建造者模式和模板方法模式。
疏漏之处恭请雅正,良策佳议敬候惠示,凡所赐教必当铭感于心。