zoukankan      html  css  js  c++  java
  • java 模块化

    java9出了模块,作为一名主要用java的程序员,所以要提前学习,保持一颗好学的心.

    1.创建模块

     新建java project com.horstmann.greet,eclipse新版会提示是否要创建模块,

    ,如果在此输入模块名字的话就会生成一个module-info.java类,是模块的描述信息类,主要包含以下内容

     到此一个模块就创建好了,如果没有在创建的时候输入模块,也可以自己新建module-info.java类来创建模块.

    2. 暴露模块

    我们创建一个接口

    package com.horstmann.greet;
    
    public interface Greeter {
        static Greeter newInstance() {
            return new com.horstmann.greet.internal.GreeterImpl();
        }
        String greet(String subject);
        
    }

    和它的实现类

    package com.horstmann.greet.internal;
    
    import com.horstmann.greet.Greeter;
    
    public class GreeterImpl implements Greeter {
    
        @Override
        public String greet(String subject) {
            // TODO Auto-generated method stub
            return "Hello, " + subject + "!";
        }
    
    }

    目录结构如下

     一般来说都会暴露模块的接口,而不是实现类,类似于es6中的模块,我们直接exports包即可

    module com.horstmann.greet {
        exports com.horstmann.greet;
    }

    这样其他模块就可以引用即可

    3.引用暴露的模块

    新建模块 v2ch09.exportedpkg

     创建类HelloWorld

    在eclipse中右键属性引入刚刚的模块

     编辑module-info.java即可引入导出的类

    module v2ch09.exportedpkg {
        requires com.horstmann.greet;
        requires hellomod.test;
    }
    public class HelloWorld {
        public static void main(String[] args) {
            Greeter greeter = Greeter.newInstance();
            System.out.println(greeter.greet("Modular World"));
        }
    }

    直接运行helloworld类,即可看到结果

    通过exports和requires,我们可以在module-info中对模块的权限进行控制,需要哪些模块,不需要哪些模块,非常方便. 

    4.模块和反射

    模块不能通过反射访问私有属性比如:

    package hellomod.test;
    
    public class ReflectTest {
        private Integer name;
    
        public ReflectTest(Integer name) {
            super();
            this.name = name;
        }
    }

    我在另一个模块通过反射访问name,会报错

    ReflectTest reflectTest = new ReflectTest(123);
            Field field = reflectTest.getClass().getDeclaredField("name");
            System.out.println(field.getInt(reflectTest));

     解决: 在要访问的模块中添加open关键词即可

    open module hellomod.test{
        exports hellomod.test;
    }

    如图 我们在module 前面添加 open即可

    或者添加exports和opens关键词

    module hellomod.test{
         exports hellomod.test;
         opens hellomod.test;
    }

    即可开放反射访问权限

     5.自动模块和不具名模块

    自动模块: 就是把jar文件放到模块路径上的模块. 为了改造以前的方式成模块,jar文件直接可以放到模块路径上成为一个新的模块

    所有包都导出,包含其他所有模块

    不具名模块: 不在模块路径中的类组成的模块.

    可以访问其他模块,但是不能被其他模块访问

    6.依赖的传递和静态模块

    如果想要传递依赖,使用 transitive关键字即可

    module v2ch09.exportedpkg {
        requires transitive com.horstmann.greet;
        requires hellomod.test;
    }

    这样,别的模块引入v2ch09.exportedpkg这个模块以后,也会自动引入com.horstmann.greet这个模块

    静态模块是 requires static,声明一个模块必须在编译时出现,运行时可选,也就是写代码的时候可以存在,但是运行以后能不能用就另外当回事了.

    7.限定导出和开放

    to关键词可以做到让模块给指定的模块开放,比如:

    module hellomod.test{
         exports hellomod.test;
         opens hellomod.test to com.horstmann.greet;
    }

    hellomod.test,只有com.horstmann.greet模块才可以使用反射,或者在exports后面加入也可以.

    8.服务加载 ServiceLoader

    ServiceLoader提供了一个机制,用于将服务和实现匹配,在模块中,可以用 provices和uses实现.

    比如:

    一个接口

    public interface GreeterService {
        void hello();
    }

    有两个实现类

    public class FrenchGreeter implements GreeterService{
    
        @Override
        public void hello() {
            System.out.println("FrenchGreeter Hello");
        }
    
    }
    public class GermanGreeterFactory implements GreeterService {
    
        @Override
        public void hello() {
            System.out.println("GermanGreeter Hello");
        }
    
    }
    module com.horstmann.greetsvc {
        exports com.horstmann.greetsvc;
        provides com.horstmann.greetsvc.GreeterService with 
            com.horstmann.greetsvc.internal.FrenchGreeter,
            com.horstmann.greetsvc.internal.GermanGreeterFactory;
    }

    在module中我们可以这样声明, provides 提供接口,with后面跟着实现类,

    在另一个模块中我们可以这样使用

        requires com.horstmann.greetsvc;
        uses com.horstmann.greetsvc.GreeterService;

    代码中这样写

            ServiceLoader<GreeterService> greeterLoader = ServiceLoader.load(GreeterService.class);
            GreeterService user = null;
            for(GreeterService greetService : greeterLoader) {
                user = greetService;
                user.hello();
            }

    我们就通过类似于 spring 方式一样,或者了GreeterService所有实现类,一个遍历直接获取了所有的实现类.

    9. 模块化工具

    jdeps jlink等,需要时在看吧.

  • 相关阅读:
    Oracle11g 审计介绍
    用Go向MySQL导入.csv文件
    【Lucene】实现全文索引
    redis-3.0.1 sentinel 主从高可用 详细配置
    MySQL性能优化之max_connections配置
    数据结构算法
    inux 软件编译、安装、删除
    2015年,才开始流行的几个教育观念
    常见的几种语言函数调用约定
    关于代码调试de那些事
  • 原文地址:https://www.cnblogs.com/lishuaiqi/p/15595633.html
Copyright © 2011-2022 走看看