启动 soul-bootstrap 可以看到日志输出了加载的一些 plugin :
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[global] [org.dromara.soul.plugin.global.GlobalPlugin]
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[sign] [org.dromara.soul.plugin.sign.SignPlugin]
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[waf] [org.dromara.soul.plugin.waf.WafPlugin]
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[rate_limiter] [org.dromara.soul.plugin.ratelimiter.RateLimiterPlugin]
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[hystrix] [org.dromara.soul.plugin.hystrix.HystrixPlugin]
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[resilience4j] [org.dromara.soul.plugin.resilience4j.Resilience4JPlugin]
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[divide] [org.dromara.soul.plugin.divide.DividePlugin]
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[webClient] [org.dromara.soul.plugin.httpclient.WebClientPlugin]
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[divide] [org.dromara.soul.plugin.divide.websocket.WebSocketPlugin]
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[alibaba-dubbo-body-param] [org.dromara.soul.plugin.alibaba.dubbo.param.BodyParamPlugin]
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[sofa] [org.dromara.soul.plugin.sofa.SofaPlugin]
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[dubbo] [org.dromara.soul.plugin.alibaba.dubbo.AlibabaDubboPlugin]
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[monitor] [org.dromara.soul.plugin.monitor.MonitorPlugin]
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[response] [org.dromara.soul.plugin.sofa.response.SofaResponsePlugin]
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[response] [org.dromara.soul.plugin.httpclient.response.WebClientResponsePlugin]
2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[response] [org.dromara.soul.plugin.alibaba.dubbo.response.DubboResponsePlugin]
根据关键字 ‘load plugin’ 我们可以定位到 SoulConfiguration 这个配置类 的 @Bean(“webHandler”)
@Bean("webHandler")
public SoulWebHandler soulWebHandler(final ObjectProvider<List<SoulPlugin>> plugins) {
List<SoulPlugin> pluginList = plugins.getIfAvailable(Collections::emptyList);
final List<SoulPlugin> soulPlugins = pluginList.stream()
.sorted(Comparator.comparingInt(SoulPlugin::getOrder)).collect(Collectors.toList());
soulPlugins.forEach(soulPlugin -> log.info("load plugin:[{}] [{}]", soulPlugin.named(), soulPlugin.getClass().getName()));
return new SoulWebHandler(soulPlugins);
}
那么为什么启动 soul-bootstrap 会去初始化 @Bean(“webHandler”) 这个Bean 呢?---- 不难发现,SoulConfiguration 类上面加了 组件扫描: @ComponentScan(“org.dromara.soul”),所以会扫描并初始化 org.dromara.soul 包下所有的 Bean
/**
* SoulConfiguration.
*
* @author xiaoyu(Myth)
*/
@Configuration
@ComponentScan("org.dromara.soul")
@Import(value = {
ErrorHandlerConfiguration.class, SoulExtConfiguration.class, SpringExtConfiguration.class})
@Slf4j
public class SoulConfiguration {
...}
我们再来看 soul-bootstrap 的代码,soul-bootstrap 里定义了 bean(在SoulNettyWebServerFactory类),通过初始化这个 bean 来创建了一个 Netty Server。
/**
* Init SoulWebHandler.
*
* @param plugins this plugins is All impl SoulPlugin.
* @return {@linkplain SoulWebHandler}
*/
@Bean("webHandler")
public SoulWebHandler soulWebHandler(final ObjectProvider<List<SoulPlugin>> plugins) {
List<SoulPlugin> pluginList = plugins.getIfAvailable(Collections::emptyList);
final List<SoulPlugin> soulPlugins = pluginList.stream()
.sorted(Comparator.comparingInt(SoulPlugin::getOrder)).collect(Collectors.toList());
soulPlugins.forEach(soulPlugin -> log.info("load plugin:[{}] [{}]", soulPlugin.named(), soulPlugin.getClass().getName()));
return new SoulWebHandler(soulPlugins);
}
那么 soul-bootstrap 启动日志里打印的 10 多个 plugin 是何时初始化好的呢?
带着这个问题,我在创建 Netty Server 的地方加了一个断点,然后查看 beanFactory
在 beanFactory 我们可以看到 Spring 已经装载了很多插件的配置类。以 SofaPluginConfiguration 为例,我们可以发现,每一个插件都自定了一个 starter,starter 的 spring.factories 文件里都指定了 自动配置:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.dromara.soul.spring.boot.starter.plugin.sofa.SofaPluginConfiguration
而 soul-bootstrap 的 pom 文件里也引入了这些插件的starter依赖,详见 soul-bootstrap 的pom文件,这里只贴出来 divide 插件的 starter 依赖:
<!--if you use http proxy start this-->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>soul-spring-boot-starter-plugin-divide</artifactId>
<version>${
project.version}</version>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>soul-spring-boot-starter-plugin-httpclient</artifactId>
<version>${
project.version}</version>
</dependency>
<!--if you use http proxy end this-->
所以为什么 sofa 插件跑起来后,请求不会转发到 soul-examples-sofa 这个项目?因为 soul-bootstrap 的 pom 文件里是没有 sofa 的starter 依赖,也就无法将 sofa 插件这个bean初始化,要解决这个问题,只要在 soul-bootstrap 的 pom 文件里加入 sofa 的starter依赖即可。
sofa starter依赖:
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>sofa-rpc-all</artifactId>
<version>5.7.6</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>soul-spring-boot-starter-plugin-sofa</artifactId>
<version>${
project.version}</version>
</dependency>
因为每个 Plugin 都实现了 SoulPlugin 这个类(相当于都是 SoulPlugin 类型),并且每个Plugin做为一个个的bean都已经自动初始化好,所以这里可以用 List 来接收找出来的所有 Plugin beans。
@Bean("webHandler")
public SoulWebHandler soulWebHandler(final ObjectProvider<List<SoulPlugin>> plugins) {
List<SoulPlugin> pluginList = plugins.getIfAvailable(Collections::emptyList);
final List<SoulPlugin> soulPlugins = pluginList.stream()
.sorted(Comparator.comparingInt(SoulPlugin::getOrder)).collect(Collectors.toList());
soulPlugins.forEach(soulPlugin -> log.info("load plugin:[{}] [{}]", soulPlugin.named(), soulPlugin.getClass().getName()));
return new SoulWebHandler(soulPlugins);
}
在 soul-bootstrap 的 pom 文件里加上了 sofa 的 starter 依赖,启动 soul-admin,soul-bootstrap 以及 example 下的 sofa-test,访问 http://localhost:9195/sofa/findAll,便可以成功访问到 sofa-test 了: