1.模块化

1.1模块化概述

由于java庞大的生态体系,导致java逐渐发展成为一门臃肿的语言,所以为了给java瘦身,让java实现轻量化,Java 9 正式的推出模块化系统。

  • Java被拆分为N多个模块,并允许Java程序可以根据需要选择加 载程序必须的Java模块,这样就可以让Java以轻量化的方式来运行

模块化的好处:

  • 模块是比包更大的程序单元,一个模块下可以包含很多包,而每个包下可以包含N多个Java类或者接口等
  • 模块之间时相对独立的,这样应用程序可以根据需要加载必须的模块
  • 此外,模块也可以作为访问权限的界定边界,可以通过模块描述文件指定哪些包需要被暴露处理,哪些包需要被隐藏,对于被隐藏的包,即使他所包含的Java类型使用了public修饰,这些Java类型也依然不能被其他模块访问

1.2 模块的基本使用(应用)

java 模版模式 java模块_Java


在模块的src目录下新建该描述性文件

该文件是用于定义模块名,访问权限和模块依赖等信息的描述性文件

java 模版模式 java模块_java 模版模式_02


只有导出包名,才可以被其他模块所访问。

java 模版模式 java模块_java 模版模式_03


要想使用哪个模块,必须指明要使用的模块名。


模块的基本使用:

  • 创建模块(按照以前的讲解方式创建模块,创建包,创建类,定义方法)为了体现模块的使用,我们创建2个模块。一个是myOne,一个是myTwo
  • 在模块的src目录下新建一个名为module-info.java的描述性文件,该文件专门定义模块名,访问权限,模块依赖等信息描述性文件中使用模块导出和模块依赖来进行配置并使用
  • 模块中所有未导出的包都是模块私有的,他们是不能在模块之外被访问的
    在myOne这个模块下的描述性文件中配置模块导出
    模块导出格式:exports 包名;
  • 一个模块要访问其他的模块,必须明确指定依赖哪些模块,未明确指定依赖的模块不能访问在myTwo这个模块下的描述性文件中配置模块依赖
    模块依赖格式:requires 模块名;
    注意:写模块名报错,需要按下Alt+Enter提示,然后选择模块依赖
  • 在myTwo这个模块的类中使用依赖模块下的内容
myOne模块下的module-info.java文件

module myOne {
     exports com.Clearlast_01;//表名要导出的包名,方便其他模块使用。
     exports com.Clearlast_02;
     exports com.Clearlast_03;

     provides MyService with Chaoji;
}

mytwo模块下的module-info.java文件
module myTwo {
     requires myOne;//指出要使用的模块名
     uses MyService;
}

1.3 模块服务的使用(应用)

Java6开始,Java提供了一种服务机制,服务使用者只面向接口编程,但不清楚服务提供者的实现类。
Java9的模块化系统简化了Java的服务机制。

  1. Java9允许将服务接口定义在一个模块中,并使用uses语句来声明该服务接口
  2. 然后对该服务接口提供不同的服务实现类,这些服务实现类可以分布在不同的模块中
  3. 服务实现模块则使用provides语句为服务接口指定实现类。
  4. 服务使用者只需要面向接口编程即可。

应用场景:

  1. 一个接口,二个实现类存在于myOne模块下
  2. myTwo模块下的测试类通过服务实现类,去加载接口的Class类,并遍历该接口,调用实现类重写的方法。

代码示例:

module-info.java文件

myOne模块下的module-info.java文件

module myOne {
     exports com.Clearlast_01;//表名要导出的包名,方便其他模块使用。
     exports com.Clearlast_02;
     exports com.Clearlast_03;

     provides MyService with Chaoji;
}

mytwo模块下的module-info.java文件
module myTwo {
     requires myOne;//指出要使用的模块名
     uses MyService;
}
------------------------------------------------------------------
实现类:
public class Chaoji implements MyService {
    @Override
    public void service() {
        System.out.println("我是超级");
    }
}

public class Mali implements MyService {

    @Override
    public void service() {
        System.out.println("我是玛丽");
    }
}
------------------------------------------------------------------
接口
public interface MyService {
    void service();
}
------------------------------------------------------------------
myTwo模块下的测试类

public class MyTest02 {
    public static void main(String[] args) {
    //加载服务
        ServiceLoader<MyService> sl = ServiceLoader.load(MyService.class);
        //遍历
        for (MyService myService : sl) {
            myService.service();
        }
    }
}

执行结果:
我是超级

module-info.java文件中

  • myOne模块中,使用provides,声明了接口的实现类 MyService with Chaoji;
  • myTwo模块中,使用uses ,声明了MyService该服务接口;
  • 在myTwo模块中,使用测试类来测试,使用ServiceLoader类来加载服务,完成接口的服务实现

在测试类的代码中

  • 通过遍历,来调用接口的service方法,而调用的这个service方法实际上是在调用myOne模块的module-info.java文件中使用provides声明接口的实现类Chaoji的service方法;