java-spi机制

作者: AmeeLove | 来源:发表于2018-04-03 16:44 被阅读24次

    java spi的具体约定如下 :

    当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。

    基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。

    pom.xml

      <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.6</version>
    </dependency>
    

    项目结构

    image.png

    system.properties,test.properties

    image.png
    image.png

    接口ISysConfig

    package com.ghg.spi.service;
    
    import java.util.Map;
    
    public interface ISysConfig {
    
        /**
         * 加载所有配置参数
         * 
         * @throws BusinessException
         */
        void loadConfig() throws Exception;
        /**
         * 取得所有配置参数
         * 
         * @return
         */
        Map<String,Object> getAllParams();
    
        /**
         * 根据参数名取得参数值
         * 
         * @param paramKey 配置参数名
         * @return
         */
        Object getParam(String paramKey);
    
        
    }
    
    

    声明

    image.png

    工具类

    package com.ghg.spi.helper;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Properties;
    
    import org.apache.commons.lang3.StringUtils;
    
    public class PropertiesHelper {
    
        private final Properties properties = new Properties();
        /**
         * windows系统文件路径分隔符
         */
        public static final char WIN_SEPARATOR = '\\';
        /**
         * unix系统文件路径分隔符
         */
        public static final char UNIX_SEPARATOR = '/';
    
        public PropertiesHelper(String... resourcesPaths) throws IOException {
            loadProperties(resourcesPaths);
        }
    
        public Properties getProperties() {
            return properties;
        }
    
        private void loadProperties(String... resourcesPaths) throws IOException {
    
            for (String location : resourcesPaths) {
    
                if (StringUtils.isNotEmpty(location)) {
                    // 修正下路径,classLoader不以/开头
                    if (location.charAt(0) == UNIX_SEPARATOR) {
                        location = location.substring(1);
                    }
    
                    try (InputStream in = readFileFromClassPath(location)) {
                        if (in != null) {
                            properties.load(in);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                        throw e;
                    }
    
                }
            }
        }
    
        /**
         * 读取资源文件
        * @Title: readFileFromClassPath
        * @Description: TODO(这里用一句话描述这个方法的作用)
        * @param @param filePath
        * @param @return    设定文件
        * @return InputStream    返回类型
        * @throws
         */
        protected InputStream readFileFromClassPath(String filePath) {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    
            if (classLoader == null) {
                classLoader = PropertiesHelper.class.getClassLoader();
            }
    
            if (filePath.charAt(0) == UNIX_SEPARATOR) {
                filePath = filePath.substring(1);
            }
    
            return classLoader.getResourceAsStream(filePath);
        }
    }
    
    

    实现

    package com.ghg.spi.imp;
    
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.Properties;
    import java.util.concurrent.atomic.AtomicBoolean;
    
    import org.apache.commons.lang3.ArrayUtils;
    
    import com.ghg.spi.helper.PropertiesHelper;
    import com.ghg.spi.service.ISysConfig;
    
    
    public class BaseSysConfig implements ISysConfig {
    
        private String[] propertiesFiles;
        private static final Map<String,Object> paramMap = new HashMap<>();
        private static AtomicBoolean isLoaded = new AtomicBoolean(false);
        
        
        
        public BaseSysConfig() throws Exception {
           // propertiesFiles = new String[]{ "system.properties" };
            this("system.properties","test.properties");
        }
        
        /**
         * 构造函数,指定配置文件
         * 
         * @param configFiles
         * @throws Exception
         */
        public BaseSysConfig(String... configFiles) throws Exception {
            propertiesFiles = configFiles;
            loadConfig();
        }
    
    
        /**
         * 加载配置文件
         */
        public synchronized void loadConfig() throws Exception {
            /**
             * 判断是否已经加载
             */
            if(!isLoaded.get()) {
                
                try {
                    loadFromConfigFile();
                } catch (Exception e) {
                    throw new Exception();
                }
            }
            isLoaded.set(true);
            
        }
    
        /**
         * @throws IOException 
         * 加载
        * @Title: loadFromConfigFile
        * @Description: TODO(这里用一句话描述这个方法的作用)
        * @param     设定文件
        * @return void    返回类型
        * @throws
         */
        protected void loadFromConfigFile() throws IOException {
            
            if(ArrayUtils.isNotEmpty(propertiesFiles)) {
                
                PropertiesHelper propertiesHelper = new PropertiesHelper(propertiesFiles);
                
                Properties properties = propertiesHelper.getProperties();
                
                if(properties!=null&& !properties.isEmpty()) {
                    
                    for(Entry<Object,Object> prop:properties.entrySet()) {
                        
                        paramMap.put(String.valueOf(prop.getKey()), prop.getValue());
                    }
                    
                }else {
                    System.out.println("未设置参数配置文件");
                }
                
            }
            
        }
    
        public Map<String,Object> getAllParams() {
            return paramMap;
        }
    
        public Object getParam(String paramKey) {
            return paramMap.get(paramKey);
        }
    
    }
    
    

    测试

    package com.ghg.spi.test;
    
    import com.ghg.spi.imp.BaseSysConfig;
    
    public class Test1 {
    
        public static void main(String[] args) throws Exception {
            BaseSysConfig baseSysConfig = new BaseSysConfig();
            
            System.out.println(baseSysConfig.getAllParams());
            System.out.println(baseSysConfig.getParam("debugMode"));
    
        }
    
    }
    
    
    image.png

    加载

    public class Test2 {
    
        public static void main(String[] args) {
            ServiceLoader<ISysConfig> serviceLoader = ServiceLoader.load(ISysConfig.class);
            
            System.out.println(serviceLoader.toString());
            Iterator<ISysConfig> iterator = serviceLoader.iterator();
            
            System.out.println(iterator.next().getAllParams());
    
        }
    
    }
    

    相关文章

      网友评论

        本文标题:java-spi机制

        本文链接:https://www.haomeiwen.com/subject/cdlchftx.html