SPI简介

SPI 全称为 Service Provider Interface,是一种服务发现机制.

说白了是啥呢,比如你有个接口,该接口有3个实现类,那么在系统运行时,这个接口到底选择哪个实现类呢?这就需要SPI了,需要根据指定的配置或者是默认的配置,找到对应的实现类加载进来,然后使用该实现类的实例.

  1. @SPI("alipay")
  2. public interface IOrderService {
  3. //支付方式
  4. String way();
  5. }
  6. public class AlipayOrderImpl implements IOrderService {
  7. @Override
  8. public String way() {
  9. System.out.println("---支付宝way()---");
  10. return "支付宝支付";
  11. }
  12. }
  13. public class WeChatOrderImpl implements IOrderService {
  14. @Override
  15. public String way() {
  16. System.out.println("---微信way()---");
  17. return "微信支付";
  18. }
  19. }
  20. alipay=com.city.common.spi.extension.AlipayOrderImpl
  21. weChat=com.city.common.spi.extension.WeChatOrderImpl
  22. public class SPITest {
  23. @Test
  24. public void test1(){
  25. ExtensionLoader<IOrderService> loader = ExtensionLoader.getExtensionLoader(IOrderService.class);
  26. //加载
  27. IOrderService alipay = loader.getExtension("alipay");
  28. System.out.println(alipay.way());
  29. IOrderService weChat = loader.getExtension("weChat");
  30. System.out.println(weChat.way());
  31. }
  32. }

Adaptive自适应扩展类加载

jdk自带编译方式
javassist dubbo默认编译方式

类的扩展

  1. @Adaptive
  2. public class AdaptiveOrderImpl implements IOrderService {
  3. //扩展类名
  4. private String orderName;
  5. public void setOrderName(String orderName) {
  6. this.orderName = orderName;
  7. }
  8. @Override
  9. public String way() {
  10. //获取IOrderService实例
  11. ExtensionLoader<IOrderService> loader = ExtensionLoader.getExtensionLoader(IOrderService.class);
  12. IOrderService order;
  13. if(StringUtils.isEmpty(orderName)){
  14. //获取默认的实例
  15. order = loader.getDefaultExtension();
  16. }else{
  17. //获取指定实例
  18. order = loader.getExtension(orderName);
  19. }
  20. return order.way();
  21. }
  22. }
  23. adaptive=com.city.common.spi.adaptive.AdaptiveOrderImpl
  24. public class AdaptiveClassTest {
  25. @Test
  26. public void test01(){
  27. ExtensionLoader<IOrderService> loader = ExtensionLoader.getExtensionLoader(IOrderService.class);
  28. //获取自适应扩展类
  29. IOrderService adativeExtension = loader.getAdaptiveExtension();
  30. ((AdaptiveOrderImpl)adativeExtension).setOrderName("weChat");
  31. System.out.println(adativeExtension.way());
  32. }
  33. @Test
  34. public void test02(){
  35. ExtensionLoader<IOrderService> loader = ExtensionLoader.getExtensionLoader(IOrderService.class);
  36. //获取自适应扩展类
  37. IOrderService adativeExtension = loader.getAdaptiveExtension();
  38. System.out.println(adativeExtension.way());
  39. }
  40. @Test
  41. public void test03(){
  42. ExtensionLoader<IOrderService> loader = ExtensionLoader.getExtensionLoader(IOrderService.class);
  43. //获取真正的扩展类
  44. Set<String> extensions = loader.getSupportedExtensions();
  45. System.out.println(extensions);
  46. }
  47. }

方法的扩展

  1. @SPI("alipay")
  2. public interface IOrderService {
  3. //支付方式
  4. String way();
  5. @Adaptive
  6. String pay(URL url);
  7. }
  8. alipay=com.city.common.spi.extension.AlipayOrderImpl
  9. weChat=com.city.common.spi.extension.WeChatOrderImpl
  10. public class AdaptiveMethodTest {
  11. @Test
  12. public void test01(){
  13. ExtensionLoader<IOrderService> loader = ExtensionLoader.getExtensionLoader(IOrderService.class);
  14. //获取自适应扩展类
  15. IOrderService adaptiveExtension = loader.getAdaptiveExtension();
  16. //模拟一个URL
  17. URL url = URL.valueOf("xxxx://localhost/ooo");
  18. System.out.println(adaptiveExtension.pay(url));
  19. }
  20. @Test
  21. public void test02(){
  22. ExtensionLoader<IOrderService> loader = ExtensionLoader.getExtensionLoader(IOrderService.class);
  23. //获取自适应扩展类
  24. IOrderService adaptiveExtension = loader.getAdaptiveExtension();
  25. //模拟一个URL
  26. URL url = URL.valueOf("xxxx://localhost/ooo?i.order.service=weChat");
  27. System.out.println(adaptiveExtension.pay(url));
  28. }
  29. }

自适应生成的扩展类

  1. package com.city.common.spi;
  2. import org.apache.dubbo.common.extension.ExtensionLoader;
  3. public class IOrderService$Adaptive implements com.city.common.spi.IOrderService {
  4. public java.lang.String pay(org.apache.dubbo.common.URL arg0) {
  5. if (arg0 == null) throw new IllegalArgumentException("url == null");
  6. org.apache.dubbo.common.URL url = arg0;
  7. String extName = url.getParameter("i.order.service", "alipay");
  8. if(extName == null) throw new IllegalStateException("Failed to get extension (com.city.common.spi.IOrderService) name from url (" + url.toString() + ") use keys([i.order.service])");
  9. com.city.common.spi.IOrderService extension = (com.city.common.spi.IOrderService)ExtensionLoader.getExtensionLoader(com.city.common.spi.IOrderService.class).getExtension(extName);
  10. return extension.pay(arg0);
  11. }
  12. public java.lang.String way() {
  13. throw new UnsupportedOperationException("The method public abstract java.lang.String com.city.common.spi.IOrderService.way() of interface com.city.common.spi.IOrderService is not adaptive method!");
  14. }
  15. }

Wrapper机制

包装目标对象进行增强

  1. public class OrderWrapper implements IOrderService {
  2. private IOrderService order;
  3. public OrderWrapper(IOrderService order) {
  4. this.order = order;
  5. }
  6. @Override
  7. public String way() {
  8. System.out.println("before-设置wrapper对pay()的增强");
  9. String way = order.way();
  10. System.out.println("after-设置wrapper对pay()的增强");
  11. return way;
  12. }
  13. @Override
  14. public String pay(URL url) {
  15. System.out.println("before-设置wrapper对pay()的增强");
  16. String pay = order.pay(url);
  17. System.out.println("after-设置wrapper对pay()的增强");
  18. return pay;
  19. }
  20. }
  21. wrapper=com.city.common.spi.wrapper.OrderWrapper

Activate机制

@Activate的作用就是为当前扩展类添加一个用于帅选的标签
group 属性 与 value 属性的关系为 与

SPI 自适应扩展原理