SpringBoot WebServer自定义实现原理(源码解析

2020-03-11  本文已影响0人  每天进步一丢儿丢儿

该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的原理解析完毕。

上一篇 下一篇

猜你喜欢

热点阅读