dubbo可扩展的点的类的对象创建 都是用类似javaspi和javasist的思想来做的。所以看后面代码 先熟悉一下java的SPI和javasist的使用

如ServicesConfig的代码

private static final Protocol protocol = (Protocol)ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

JAVASPI的作用

服务(接口实现类)的自动发现。我们定义好一组接口标准。而具体实现调用者根据自身需求自己实现

JavaSPI简单使用

我们模拟我们做了一个框架(jar)  框架的正常运行需要相关配置。配置加载方式由使用者来实现

1.定义接口

/**
 * 加载配置文件的句柄
 */
public interface LoadConfigHandle {
    public String  load();
}

2.定义实现类

public class HttpLoadConfigHandle implements LoadConfigHandle {
    public String load() {
        System.out.println("正在用http请求加载配置文件数据");
        return "";
    }
}
public class XmlLoadConfigHandle implements LoadConfigHandle {
    public String load() {
        System.out.println("正在加载配置文件xml");
        return "";
    }
}

在resource创建META-INF文件夹,再创建一个与接口全名称同名的文件。将实现类配置进去

com.liqiang.spi.XmlLoadConfigHandle
com.liqiang.spi.HttpLoadConfigHandle

3测试

public static void main(String[] str) throws InterruptedException {
        ServiceLoader<LoadConfigHandle> serviceLoader = ServiceLoader.load(LoadConfigHandle.class);
        Iterator<LoadConfigHandle> iterator = serviceLoader.iterator();
        while (iterator.hasNext()) {//next时候查缓存有没有加载过。如果没有加载才去加载
            LoadConfigHandle loadConfigHandle = iterator.next();//next时候查缓存有没有加载过。如果没有加载采取加载
loadConfigHandle.load(); } }

javasist使用

假设我们在运行时要动态的创建和编译类这样一个类

package com.liqiang.ssist;

public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Person(String name, int age){
         this.name=name;
         this.age=age;
    }
    public void  show(String ... date){
        System.out.println(this.name+"|"+this.age);
    }
}
  public static  void  main(String[]str) throws Exception{
        //ClassPool:CtClass对象的容器
        ClassPool pool = ClassPool.getDefault();
        //通过ClassPool生成一个public新类Emp.java
        CtClass ctClass = pool.makeClass("com.liqiang.ssist.Person");
        /**
         * 创建字段
         */
        //创建字段private String name;
        CtField  nameField = new CtField(pool.getCtClass("java.lang.String"),"name",ctClass);
        nameField.setModifiers(Modifier.PRIVATE);//私有字段
        ctClass.addField(nameField);
        //创建字段private int age;
        CtField  ageField = new CtField(pool.getCtClass("java.lang.Integer"),"age",ctClass);
        ageField.setModifiers(Modifier.PRIVATE);//私有字段
        ctClass.addField(ageField);
        /**
         * 为他们添加添加get set个访问器
         */
        ctClass.addMethod(CtNewMethod.getter("getName", nameField));
        ctClass.addMethod(CtNewMethod.setter("setName", nameField));
        ctClass.addMethod(CtNewMethod.getter("getAge", ageField));
        ctClass.addMethod(CtNewMethod.setter("setAge", ageField));
        /**
         * 添加构造函数
         */
        CtConstructor ctConstructor = new CtConstructor(new CtClass[]{pool.getCtClass("java.lang.String"),
                pool.getCtClass("java.lang.Integer")}, ctClass);
        //为构造函数设置函数体$1表示第一个参数 $2表示第二个参数
        StringBuffer buffer = new StringBuffer();
        buffer.append("{\n")
                .append("name=$1;\n")
                .append("age=$2;\n}");
        ctConstructor.setBody(buffer.toString());
        //把构造函数添加到新的类中
        ctClass.addConstructor(ctConstructor);
        /**
         * 定义方法
         */
        CtMethod ctMethod = new CtMethod(CtClass.voidType,"show",new CtClass[]{},ctClass);
        //为自定义方法设置修饰符
        ctMethod.setModifiers(Modifier.PUBLIC);
        //为自定义方法设置函数体
        StringBuffer buffer2 = new StringBuffer();
        buffer2.append("{\nSystem.out.println(this.name+\"|\"+this.age);\n")
                .append("}");
        ctMethod.setBody(buffer2.toString());
        ctClass.addMethod(ctMethod);
        /**
         * 反射生成实体
         */
        Class<?> clazz = ctClass.toClass();
        Constructor cla = clazz.getDeclaredConstructor(String.class,Integer.class);//获取构造函数的构造器

        Object obj=cla.newInstance("小明",12);//调用构造器生成对象
        obj.getClass().getMethod("show", new Class[]{}).invoke(obj, new Object[]{});
    }

输出

还有更多的使用方法 动态继承实现类。动态改变类方法 增加方法等。

dubbo-源码阅读之javaspi&javasist简单使用的更多相关文章

  1. 【Dubbo源码阅读系列】之远程服务调用(上)

    今天打算来讲一讲 Dubbo 服务远程调用.笔者在开始看 Dubbo 远程服务相关源码的时候,看的有点迷糊.后来慢慢明白 Dubbo 远程服务的调用的本质就是动态代理模式的一种实现.本地消费者无须知道 ...

  2. 【Dubbo源码阅读系列】服务暴露之远程暴露

    引言 什么叫 远程暴露 ?试着想象着这么一种场景:假设我们新增了一台服务器 A,专门用于发送短信提示给指定用户.那么问题来了,我们的 Message 服务上线之后,应该如何告知调用方服务器,服务器 A ...

  3. 【Dubbo源码阅读系列】服务暴露之本地暴露

    在上一篇文章中我们介绍 Dubbo 自定义标签解析相关内容,其中我们自定义的 XML 标签 <dubbo:service /> 会被解析为 ServiceBean 对象(传送门:Dubbo ...

  4. 【Dubbo源码阅读系列】之 Dubbo SPI 机制

    最近抽空开始了 Dubbo 源码的阅读之旅,希望可以通过写文章的方式记录和分享自己对 Dubbo 的理解.如果在本文出现一些纰漏或者错误之处,也希望大家不吝指出. Dubbo SPI 介绍 Java ...

  5. Dubbo源码阅读顺序

    转载: https://blog.csdn.net/heroqiang/article/details/85340958 Dubbo源码解析之配置解析篇,主要内容是<dubbo:service/ ...

  6. Dubbo源码阅读-服务导出

    Dubbo服务导出过程始于Spring容器发布刷新事件,Dubbo在接收到事件后,会立即执行服务导出逻辑.整个逻辑大致可分为三个部分,第一部分是前置工作,主要用于检查参数,组装URL.第二部分是导出服 ...

  7. dubbo源码阅读之SPI

    dubbo SPI SPI,全程Service Provider interface, java中的一种借口扩展机制,将借口的实现类注明在配置文件中,程序在运行时通过扫描这些配置文件从而获取全部的实现 ...

  8. dubbo源码阅读之自适应扩展

    自适应扩展机制 刚开始看代码,其实并不能很好地理解dubbo的自适应扩展机制的作用,我们不妨先把代码的主要逻辑过一遍,梳理一下,在了解了代码细节之后,回过头再来思考自适应扩展的作用,dubbo为什么要 ...

  9. 【Dubbo源码阅读系列】之 Dubbo XML 配置加载

    今天我们来谈谈 Dubbo XML 配置相关内容.关于这部分内容我打算分为以下几个部分进行介绍: Dubbo XML Spring 自定义 XML 标签解析 Dubbo 自定义 XML 标签解析 Du ...

随机推荐

  1. oc56--ARC多个对象的内存管理

    // main.m // ARC中多个对象的内存管理:ARC的内存管理就是MRC的内存管理(一个对象释放的时候,必然会把它里面的对象释放),只不过一个是Xcode加的代码,一个是我们自己加的代码: / ...

  2. hdoj-1896 stones

    Stones Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Sub ...

  3. gitlab克隆报错:remote: HTTP Basic: Access denied;remote: You must use a personal access token with ‘api’ scope for Git over HTTP.

    错误: remote: HTTP Basic: Access denied remote: You must use a personal access token with ‘api’ scope ...

  4. MyEclipse配置https

    1.参照CAS配置(1)SSL证书配置文章配置证书. 2.打开myeclipse的Workspace下的.metadata/.me_tcat7/conf/server.xml 打开文件,添加如下代码 ...

  5. org.apache.catalina.core.StandardContext startInternal SEVERE: Error listenerStart

    问题:文件明明存在,资源找不到,报错 解决方法:原因是没有build path,这有点像.net里边的build .点击相应的文件夹选择build path ,解决问题

  6. java.util.Date

    package com.etc.usual; import java.util.Calendar; import java.util.Date; /** * * @author Administrat ...

  7. struts2框架搭建(一)

    struts2是一个基于mvc的web应用框架.struts2本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器层(Controller)来建立模型与视图的数据交互. str ...

  8. Application windows are expected to have a root view controller at the end of application launch

    今天把Xcode升级了,模拟器 用的12.1的系统,运行时发现项目总是崩溃,采用9.3系统的测试机发现错误日志如下: Application windows are expected to have ...

  9. Android自定义开机和关机动画

    Android自定义开机和关机动画 Android在开机的过程中,会经历三张图片,关于静态图的修改在我的这篇文章中有介绍到: Android开机图片替换 现在要介绍的是怎么用动画替换静态图片.开/关机 ...

  10. js实现“级联菜单”

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...