该Web服务自定义工厂的自定义的思想是在一个WebServerFactoryCustomizer接口的customize方法中持有需要自定义的工厂类,并在该接口的实现类中调用工厂类的API对工厂类进行重新配置。只不过此处利用Spring容器的特性,将一系列的操作交给容器自动完成,使用者只需要提供对WebServerFactoryCustomizer的具体实现,在自定义方法通过工厂类的API对工厂进行自定义配置即可,下面结合源码详细说明。
@FunctionalInterface
public interface WebServerFactoryCustomizer<T extends WebServerFactory> {
/**
* Customize the specified {@link WebServerFactory}.
* @param factory the web server factory to customize
*/
void customize(T factory);
}
需要对SpringBoot环境的web服务器进行自定义设置的用户,可以实现该接口,在customize方法中调用指定的WebServerFactory子类的方法进行个性化设置,就像下面这样
@Component
public class MyTomcatWebServerCustomizer
implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Override
public void customize(TomcatServletWebServerFactory factory) {
// customize the factory here
}
}
那么customize方法是怎样生效的呢?看一下下面这个类
public class WebServerFactoryCustomizerBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
private ListableBeanFactory beanFactory;
private List<WebServerFactoryCustomizer<?>> customizers;
@Override
public void setBeanFactory(BeanFactory beanFactory) {
Assert.isInstanceOf(ListableBeanFactory.class, beanFactory,
"WebServerCustomizerBeanPostProcessor can only be used with a ListableBeanFactory");
this.beanFactory = (ListableBeanFactory) beanFactory;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebServerFactory) {
postProcessBeforeInitialization((WebServerFactory) bean);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@SuppressWarnings("unchecked")
private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory)
.withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)
.invoke((customizer) -> customizer.customize(webServerFactory));
}
private Collection<WebServerFactoryCustomizer<?>> getCustomizers() {
if (this.customizers == null) {
// Look up does not include the parent context
this.customizers = new ArrayList<>(getWebServerFactoryCustomizerBeans());
this.customizers.sort(AnnotationAwareOrderComparator.INSTANCE);
this.customizers = Collections.unmodifiableList(this.customizers);
}
return this.customizers;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Collection<WebServerFactoryCustomizer<?>> getWebServerFactoryCustomizerBeans() {
return (Collection) this.beanFactory.getBeansOfType(WebServerFactoryCustomizer.class, false, false).values();
}
}
此类实现了BeanPostProcessor和BeanFactoryAware 接口,类中还持有了WebServerFactoryCustomizer的一个集合,BeanPostProcessor和BeanFactoryAware中的方法分别会在bean实例化和Spring容器实例化的时候回调。该类中有一个getWebServerFactoryCustomizerBeans的方法,顾名思义该方法会将容器中的所有的WebServerFactoryCustomizer类型全部获取,getCustomizers会将获取的WebServerFactoryCustomizer类进行一些简单的处理。重点来了,那么customize方法是在什么时候被调用的呢?请看下面的代码段。
@SuppressWarnings("unchecked")
private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory)
.withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)
.invoke((customizer) -> customizer.customize(webServerFactory));
}
这里就是对所有实现WebServerFactoryCustomizer类进行方法调用的地方。postProcessBeforeInitialization方法最终会被BeanPostProcessor的postProcessBeforeInitialization回调方法调用,我们看到这个方法是在Bean初始化之前触发的,所以这个方法可以对容器中的Bean实现初始化之前的一些个性化的修改。
看到此处我们可能有一个疑惑,这个类是怎样注册到Spring容器中的呢?请看这段代码:
public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
private ConfigurableListableBeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (beanFactory instanceof ConfigurableListableBeanFactory) {
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
}
}
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
if (this.beanFactory == null) {
return;
}
registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor",
WebServerFactoryCustomizerBeanPostProcessor.class);
registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor",
ErrorPageRegistrarBeanPostProcessor.class);
}
private void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, String name, Class<?> beanClass) {
if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(beanClass, true, false))) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
beanDefinition.setSynthetic(true);
registry.registerBeanDefinition(name, beanDefinition);
}
}
}
这个类的逻辑很简单,就是一个实现了ImportBeanDefinitionRegistrar和BeanFactoryAware接口的类,先从Spring容器中查找WebServerFactoryCustomizerBeanPostProcessor类型的Bean,如果没有就创建一个WebServerFactoryCustomizerBeanPostProcessor类型的RootBeanDefinition并注册到Spring容器中,到此SpringBoot自定义配置web server的原理解析完毕。
网友评论