zoukankan      html  css  js  c++  java
  • dubbo源码阅读-配置(四)之javaSPI和javasis使用demo

    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("{
    ")
                    .append("name=$1;
    ")
                    .append("age=$2;
    }");
            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("{
    System.out.println(this.name+"|"+this.age);
    ")
                    .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[]{});
        }

    输出

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

  • 相关阅读:
    移动端测试作业小集合 (6)
    移动端测试——手机常见操作的API (5)
    移动端测试——APP元素信息、事件操作、模拟手势API(4)
    移动端测试——APP元素定位操作 (3)
    移动端测试——App基础操作(2)
    移动端测试基础 (1)
    Python进阶-一切皆对象及type-object-class间的关系
    故障-解决pip安装mysqlclient、gevent报找不到cc或gcc错误问题
    Linux环境上部署Flask
    解决多版本共存时,python/pip等命令失效
  • 原文地址:https://www.cnblogs.com/LQBlog/p/12449357.html
Copyright © 2011-2022 走看看