分布式RPC系统框架Dubbo-23Dubbo的内核解析-Wrapper机制

        Wrapper机制,即扩展类的包装机制;就是对扩展类中的SPI接口方法进行增强,进行包装,是AOP思想的提现,是Wrapper(装饰者)设计模式的应用(是一种特例的装饰者设计模式),一个SPI可以包含多个Wrapper。

注意,Wrapper类不属于“拓展类”;

1.Wrapper类规范

Wrapper机制不是通过注解实现的,而是通过Wrapper类实现,Wrapper类在定义时需要遵循如下规范:

  • 类要实现SPI接口;

  • 类中要有SPI接口的引用;

  • 在接口实现方法中要调用SPI接口引用对象的相应方法;

  • 类名称一般以Wrapper结尾(规范约定,非必须)

2.源码示例

filter=org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper
listener=org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper
mock=org.apache.dubbo.rpc.support.MockProtocol
//################Protocol#######################
package org.apache.dubbo.rpc;

import ***

/**
 * Protocol. (API/SPI, Singleton, ThreadSafe)
 */
@SPI("dubbo")
public interface Protocol {

    int getDefaultPort();
	//*@Adaptive修饰的方法,会生成扩展类
    @Adaptive
    <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
	//*@Adaptive修饰的方法,会生成扩展类
    @Adaptive
    <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;

    void destroy();

    default List<ProtocolServer> getServers() {
        return Collections.emptyList();
    }
}


//##############ProtocolFilterWrapper#############
package org.apache.dubbo.rpc.protocol;

import ***

/**
 * ListenerProtocol
 */
@Activate(order = 100)
//1-实现Protocol接口,即实现一个SPI接口
public class ProtocolFilterWrapper implements Protocol {
	//2-包含Protocol的引用
    private final Protocol protocol;

    public ProtocolFilterWrapper(Protocol protocol) {
        if (protocol == null) {
            throw new IllegalArgumentException("protocol == null");
        }
        this.protocol = protocol;
    }

    private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
        ...
    }

    @Override
    public int getDefaultPort() {
    	//3-实现方法中调用引用的方法
        return protocol.getDefaultPort();
    }

    @Override
    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
    
        if (UrlUtils.isRegistry(invoker.getUrl())) {
            return protocol.export(invoker);
        }
        //增强引用方法,此为Wrapper装饰者模式的主要目的
        return protocol.export(buildInvokerChain(invoker, SERVICE_FILTER_KEY, CommonConstants.PROVIDER));
    }

    @Override
    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
        if (UrlUtils.isRegistry(url)) {
            return protocol.refer(type, url);
        }
        return buildInvokerChain(protocol.refer(type, url), REFERENCE_FILTER_KEY, CommonConstants.CONSUMER);
    }

    @Override
    public void destroy() {
        protocol.destroy();
    }

    @Override
    public List<ProtocolServer> getServers() {
        return protocol.getServers();
    }

}

3.示例代码

(1)创建工程wapper导入dubbo依赖

<!-- dubbo依赖 --> 
	<dependency>
	    <groupId>org.apache.dubbo</groupId>
	    <artifactId>dubbo</artifactId>
	    <version>2.7.0</version>
	</dependency>

(2)创建提供者路径及配置文件

alipay=com.zxy.spi.extension.AlipayOrder
wechat=com.zxy.spi.extension.WeChatOrder
wrapper=com.zxy.spi.extension.OrderWrapper
wrapper2=com.zxy.spi.extension.OrderWrapper2

(3)创建接口及实现类

/**
 * SPI标签,设置默认为alipay阿里支付
 */
@SPI("alipay")
public interface Order {
	//支付方式
	String way();
	//支付
	@Adaptive
	String pay(URL url);
}
//###################################################
public class AlipayOrder implements Order{
	public String way() {
		System.out.println("---支付宝way()---");
		return "支付宝支付方式";
	}

	@Override
	public String pay(URL url) {
		System.out.println("---支付宝pay()---");
		return "使用支付宝支付";
	}
}
//###################################################
public class WeChatOrder implements Order{

	public String way() {
		System.out.println("---微信way()---");
		return "微信支付方式";
	}

	@Override
	public String pay(URL url) {
		System.out.println("---微信pay()---");
		return "使用微信支付";
	}
}
//###################################################
public class OrderWrapper implements Order{

	private Order order;
	
	public OrderWrapper(Order order) {
		this.order = order;
	}
	
	@Override
	public String way() {
		System.out.println("before-这是wrapper对way()方法的增强!");
		String way = order.way();
		System.out.println("after-这是wrapper对way()方法的增强!");
		return way;
	}

	@Override
	public String pay(URL url) {
		System.out.println("before-这是wrapper对pay()方法的增强!");
		String pay = order.pay(url);
		System.out.println("after-这是wrapper对pay()方法的增强!");
		return pay;
	}

}
//###################################################
public class OrderWrapper2 implements Order{

	private Order order;
	
	public OrderWrapper2(Order order) {
		this.order = order;
	}
	
	@Override
	public String way() {
		System.out.println("22222before-这是wrapper对way()方法的增强!");
		String way = order.way();
		System.out.println("22222after-这是wrapper对way()方法的增强!");
		return way;
	}

	@Override
	public String pay(URL url) {
		System.out.println("22222before-这是wrapper对pay()方法的增强!");
		String pay = order.pay(url);
		System.out.println("22222after-这是wrapper对pay()方法的增强!");
		return pay;
	}
}

(4)定义测试启动类

public class OrderTest {

	public static void main(String[] args) {
		
		ExtensionLoader<Order> loader = ExtensionLoader.getExtensionLoader(Order.class);
		// 获取自适应AdaptiveExtension
		Order adaptiveExtension = loader.getAdaptiveExtension();
		//模拟一个URL,不指定支付方式使用默认
		URL url = URL.valueOf("xxx://localhost/ooo");
		System.out.println(adaptiveExtension.pay(url));
	}
}

(5)运行结果

        结果中输出顺序说明,先运行外部增强OrderWapper2,然后执行内部增强OrderWapper,此运行顺序是由META-INF中的order注册文件决定,执行顺序是倒序执行;

4.Wrapper作用(重要)

        注意,Wrapper不属于扩展类,如示例代码中的OrderWapper并不是order接口的扩展类,真正的扩展类是AlipayOrder及WeChatOrder,而OrderWapper作用是辅助增强扩展类AlipayOrder和WeChatOrder的功能,OrderWapper不可以单独使用;

(1)通过代码验证OrderWapper不是扩展类

public class OrderTest {

	public static void main(String[] args) {
		
		ExtensionLoader<Order> loader = ExtensionLoader.getExtensionLoader(Order.class);
		
		//通过loader.getSupportedExtensions()获取order接口所有的拓展类名
		Set<String> extensions = loader.getSupportedExtensions();
		System.out.println(extensions);
	}

}

注意:由@Adaptive修饰的类同样也不是扩展类,其也不能单独使用。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值