zoukankan      html  css  js  c++  java
  • 利用java spi技术结合map解耦应用,可作为cglib和jdk动态代理的补充

    1.什么是spi?

    spi全称为service provider interface 即服务提供接口,它是用来解耦应用的,常在框架中使用。方便后期开发加入新的实现而无需修改代码

    2.本例使用spi技术实现了一个container容器,实现了按照类型注入,使用时按照约定传入类即可得到类的实例对象

    3.代码实例:

    创建一个项目spi,创建三个模块,分别对应接口定义模块spiinterfaces,版本一实现模块spiimplmodle_1和版本二实现模块spiimplmodle_2,以及一个使用方模块spiapp,项目结构如图:

    项目需求:实现一个通过拖拽构建web项目的工具,解决项目构建一体化,此处实现拖拽选择前端框架选择,如extjs框架,bootstrap框架

     3.1 接口定义(spiinterfaces)

    package spiinterfaces.scope;
    
    public interface Selector {
    
        public void select();
        
        public void select(Object obj);
    }

    3.2 extjs框架集成接口实现模拟(spiimplmodle_1)

    package spiimplmodle_1.scope;
    
    import spiinterfaces.scope.Selector;
    
    public class ExtJsSelector implements Selector{
    
        public void select() {
            System.out.println("from ExtJsSelector.select()");
        }
    
        public void select(Object obj) {
            System.out.println("from ExtJsSelector.select("+obj.toString()+")");
        }
    
    }

    3.3 在src/main/resources目录下新建文件夹META-INF,在META-INF文件夹下新建文件夹services,创建一个文件,命名为spiinterfaces.scope.Selector,内容:(spiimplmodle_1)

    spiimplmodle_1.scope.ExtJsSelector

    3.4 项目pom.xml(spiimplmodle_1)

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <parent>
        <groupId>com.gwb</groupId>
        <artifactId>spi</artifactId>
        <version>0.0.1-SNAPSHOT</version>
      </parent>
      <artifactId>spiimplmodle_1</artifactId>
      <dependencies>
          <dependency>
              <groupId>com.gwb</groupId>
              <artifactId>spiinterfaces</artifactId>
              <version>0.0.1-SNAPSHOT</version>
          </dependency>
      </dependencies>
    </project>

    3.5 bootstrap 框架集成实现(spiimplmodle_2)

    package sipimplmodle_2.scope;
    
    import spiinterfaces.scope.Selector;
    
    public class BootstrapSelector implements Selector{
    
        public void select() {
            System.out.println("from BootstrapSelector.select()");
        }
    
        public void select(Object obj) {
            System.out.println("from BootstrapSelector.select("+obj.toString()+")");
        }
    
    }

    3.6  在src/main/resources目录下新建文件夹META-INF,在META-INF文件夹下新建文件夹services,创建一个文件,命名为spiinterfaces.scope.Selector,内容:(spiimplmodle_2)

    sipimplmodle_2.scope.BootstrapSelector

    3.7 项目pom.xml(spiimplmodle_2)

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <parent>
        <groupId>com.gwb</groupId>
        <artifactId>spi</artifactId>
        <version>0.0.1-SNAPSHOT</version>
      </parent>
      <artifactId>sipimplmodle_2</artifactId>
      <dependencies>
          <dependency>
              <groupId>com.gwb</groupId>
              <artifactId>spiinterfaces</artifactId>
              <version>0.0.1-SNAPSHOT</version>
          </dependency>
      </dependencies>
    </project>

    3.8  项目pom.xml(spiapp)

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <parent>
        <groupId>com.gwb</groupId>
        <artifactId>spi</artifactId>
        <version>0.0.1-SNAPSHOT</version>
      </parent>
      <artifactId>spiapp</artifactId>
      <dependencies>
          <dependency>
              <groupId>com.gwb</groupId>
              <artifactId>spiimplmodle_1</artifactId>
              <version>0.0.1-SNAPSHOT</version>
          </dependency>
          <dependency>
              <groupId>com.gwb</groupId>
              <artifactId>sipimplmodle_2</artifactId>
              <version>0.0.1-SNAPSHOT</version>
          </dependency>
      </dependencies>
    </project>

    3.9 使用spi获取并将实例存入map(spiapp)

    package spiapp.consumer;
    
    import java.util.Map;
    import java.util.ServiceLoader;
    import java.util.concurrent.ConcurrentHashMap;
    
    import spiinterfaces.scope.Selector;
    
    /**
     * 利用spi技术,将单例的接口实现缓存起来,
     * 以类型为键,该类的实例为值,实现接口的解耦
     * @author HUAWEI
     *
     */
    public class SelectorFactory {
    
        private static Map<Class<?>, Selector> cacheMap = new ConcurrentHashMap<Class<?>, Selector>();
        static {
            ServiceLoader<Selector> selector = ServiceLoader.load(Selector.class);
            selector.iterator().forEachRemaining((s)->{
                cacheMap.put(s.getClass(), s);
            });
        }
        public static Selector getSelector(Class<?> key) {
            return cacheMap.get(key);
        }
    }

    3.9.1 使用jdk代理获取(spiapp)

    package spiapp.consumer;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class Proxy implements InvocationHandler{
    
        private Object target;
    
        @Override
        public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
            // TODO Auto-generated method stub
            return arg1.invoke(target, arg2);
        }
        public Object getJDKProxy(Object targetObject){
            //为目标对象target赋值
            this.setTarget(targetObject);
            //JDK动态代理只能针对实现了接口的类进行代理,newProxyInstance 函数所需参数就可看出
            return java.lang.reflect.Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
        }
        public Object getTarget() {
            return target;
        }
        public void setTarget(Object target) {
            this.target = target;
        }
    }

    4.0 测试类调用(spiapp)

    package spiapp.consumer;
    
    import sipimplmodle_2.scope.BootstrapSelector;
    import spiimplmodle_1.scope.ExtJsSelector;
    import spiinterfaces.scope.Selector;
    
    public class test {
    
        public static void main(String[] args) {
            useProxy();
        }
        
        public static void useFactory() {
            Selector selector = SelectorFactory.getSelector(ExtJsSelector.class);
            selector.select();
            Selector selector1 = SelectorFactory.getSelector(BootstrapSelector.class);
            selector1.select("hello spi");
        }
        
        public static void useProxy() {
            try {
                Proxy proxy = new Proxy();
                try {
                    
                    Selector selector = (Selector) proxy.getJDKProxy(ExtJsSelector.class.newInstance());
                    selector.select();
                } catch (SecurityException e) {
                    e.printStackTrace();
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    毕~

  • 相关阅读:
    免费下载小说
    前段博客云库网
    node发送邮件
    node 发送短信
    node生成uuid
    node 控制台颜色
    OfficeCommandbarDesigner20170202.rar
    OfficeCommandbarViewer20171005.rar
    VB.Net 正则表达式测试器
    Windows_Management_Instrumentation
  • 原文地址:https://www.cnblogs.com/g177w/p/14343649.html
Copyright © 2011-2022 走看看