您的位置:首页 > 编程语言 > Java开发

如何写一个给自己的框架写一个优雅的Java Config模块(二)

2017-06-28 09:33 267 查看
Configurer保存配置信息

Builder将Configurer串起来,一个Builder可能保存有很多的Configurer。多个类型的Configurer,同一个类型的多个Configurer。参看:AbstractConfiguredSecurityBuilder。

Configuration使用Builder的信息,将Builder中保存的信息转化成各种Bean注入到IOC容器中。例子:WebSecurityConfiguration使用WebSecurity(一个Builder)中的信息,构建了各种相关的Bean。

这样就对了,使用Builder将Configurer串起来,然后一起传给Configuration用户构造Bean注入IOC容器中。

一般会建立一个xxxConfigurerAdapter用于将多个Builder串起来。这就是之前一直混乱的原因。

问题1:

如何将Builder中的信息传给Configuration?

答案:

Builder和其下属的Configurer是如何互相传递信息的,

Builder会持有其所有下属的Configurer的引用,所以Builder可以主动与Configurer通信。

那么Configurer是怎么获取Builder对象的信息的呢,我们看一下Configurer的定义:

public interface WeiXinConfigurer<O, B extends WeiXinBuilder<O>> {

/**
* Initialize the {@link WeiXinBuilder}. Here only shared state should be
* created and modified, but not properties on the {@link WeiXinBuilder}
* used for building the object. This ensures that the
* {@link #configure(WeiXinBuilder)} method uses the correct shared objects
* when building.
*
* @param builder
* @throws Exception
*/
void init(B builder) throws Exception;

/**
* Configure the {@link WeiXinBuilder} by setting the necessary properties
* on the {@link WeiXinBuilder}.
*
* @param builder
* @throws Exception
*/
void configure(B builder) throws Exception;
}


可以看到,Configurer接口的两个方法的参数都是Builder,而这init和configure这两个方法都是持有此Configurer对象的引用的Builder在Builder初始化的合适的时机主动调用的。

比如在所有的Builder的上级抽象类AbstractConfiguredSecurityBuilder中有两个方法如下:

@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);
}
}


这两个方法最终会在合适的时机调用:

@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;
}
}


问题2:

AbstractConfiguredSecurityBuilder是一个可以被配置的Builder,其中有个configurers字段,类型为LinkedHashMap

public interface WeiXinConfigurer<O, B extends WeiXinBuilder<O>>


O:The object being built by the {@link WeiXinBuilder} B

B: The {@link WeiXinBuilder} that builds objects of type O. This is also the {@link WeiXinBuilder} that is being configured.

只要将这两个值泛型就可以被任意的模块调用了。

tip3:

每个子模块的配置加一个and方法,用于返回当前使用的Builder对象,接着进行Builder对象级别的配置。

@Override
protected DefaultSecurityFilterChain performBuild() throws Exception {
Collections.sort(filters, comparator);
return new DefaultSecurityFilterChain(requestMatcher, filters);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐