Java 9 Dependency Injection
上QQ阅读APP看书,第一时间看更新

Module Descriptor (module-info.java)

module-info.java is an important file in the modular system, and it contains modular metadata which describes the behavior module. It is a Java file, but it is not like a traditional Java file. It has its own syntax and it's compiled into the module-info.class file.

The following is the syntax that we have to follow when creating module-info.java:

module <module-name> {
requires <module-name-1>;
requires <module-name-2>;
.
.
requires <module-name-n>;
exports <package-1>;
.
.
exports <package-n>;
}

The following is an example of the module-info.java file, where each module contains a unique ID and optional module descriptor details:

module com.packt.java9dependency.chapter2 {
exports com.packt.java9dependency.chapter2.services;
requires com.packt.java9dependency.chapter1;
requires java.sql;
}

Let's understand different module descriptors, mentioned here:

  • requires <module>: This descriptor specifies that a module depends on another module to run this module, this type of relationship is called a module dependency. At runtime, modules only see modules that are required, and this is called Readability.
  • requires transitive <module>: This means to indicate a dependency on another module and, moreover, to guarantee that other modules perusing your module read that dependency—known as implied readability.  For example, module A reads module B and module B reads module C, then module B needs to declare requires transitive, otherwise module A will not compile unless they read module C explicitly.
  • requires static <module>: By using a static keyword, dependency will be validated at compile time and it will be optional at runtime.
  • exports <package-name>: This descriptor is used to export own packages to other modules.
  • exports <package-name> to <module-name>: By using such descriptor statements, we export packages to specific modules, not to all modules. It's called qualified export.
  • opens <package-name>: Opens descriptor used to define, only public types of packages are accessible to code in other modules at runtime only using reflection.
  • opens <package-name> to <module-name>: A qualified open. This opens only a specific module that can access public type packages at runtime only through reflection.
  • uses <service-interface>: A module directive defined service used for this module. It makes a module as a service consumer. Service implementation can be in the same module or on another module.
  • provide <service-interface> with <class1>,<class2> :  Specifies that a module contains service implementation of an interface defined in a modules's uses descriptor. This makes a module a service provider.

The following are important points that we need to understand when creating a module descriptor:

  • A module-info can have only a module name; means exports or requires clause are not mandatory.
  • If a module descriptor has only exports then it means it is only exporting declared packages to other modules and it is not dependent on any other module. We can call them independent modules. For example, the java.base module.
  • Opposite to the previous point, module descriptors might contain export and requires clauses, which means the module is exporting packages to other modules and is also dependent on other modules for its own compilation.
  •  There might be zero or more export or requires clauses in the module descriptor.
When we create a project, JDK 8 adds a JDK jar into our project ClassPath. But when we create a Java 9 module project, then JDK modules are added into ModulePath.