Com a chegada do Java 9, a plataforma Java ganhou um novo sistema de módulos, que foi uma das maiores mudanças desde a introdução das Generics no Java 5. O sistema de módulos, também conhecido como Projeto Jigsaw, permite dividir a aplicação em módulos distintos com dependências explícitas. Isso melhora a organização, segurança e manutenibilidade do código.
Introdução aos módulos
Um módulo em Java é uma unidade de agregação de pacotes. Ele encapsula pacotes e recursos e especifica quais deles são acessíveis a outros módulos e quais não são. O sistema de módulos tem como objetivo principal oferecer maior controle sobre a visibilidade de classes e pacotes e ajudar a construir aplicações mais robustas e seguras.
Definindo um módulo
Para definir um módulo, você precisa criar um arquivo module-info.java na raiz do diretório do módulo. Esse arquivo contém as declarações que definem o nome do módulo e as suas dependências.
Exemplo de um module-info.java básico:
requires java.sql;
exports com.example.myapp.api;
}
Neste exemplo:
‘module com.example.myapp’ define o nome do módulo
‘requires java.sql’ declara que este módulo depende do módulo ‘java.sql’.
exports com.example.myapp.api permite que outros módulos acessem os pacotes dentro módulo ‘com.example.myapp.api’
Estrutura do projeto com módulo
Suponha que temos dois módulos ‘com.example.myapp’ e ‘com.example.util’.
A estrutura do projeto seria algo assim:
├── com.example.myapp/
│ ├── module-info.java
│ └── com/example/myapp/
│ ├── Main.java
│ └── api/
│ └── MyService.java
└── com.example.util/
├── module-info.java
└── com/example/util/
└── Utility.java
Exemplo de implementação
Vamos implementar um exemplo simples onde um módulo com.example.myapp utiliza um serviço fornecido pelo módulo com.example.util.
com.example.util/module-info.java
exports com.example.util;
}
com.example.util/com/example/util/Utility.java
public class Utility {
public static String getGreeting() {
return “Hello from Utility!”;
}
}
com.example.myapp/module-info.java
requires com.example.util;
}
com.example.myapp/com/example/myapp/Main.java
import com.example.util.Utility;
public class Main {
public static void main(String[] args) {
System.out.println(Utility.getGreeting());
}
}
Compilação e execução dos módulos
Para compilar e executar módulos, você pode usar o comando ‘javac’ e ‘java’ com a opção ‘–module-path’ para especificar onde os módulos estão localizados.
Compilação
Execução
Recursos adicionais
Diretrizes de acesso
Você pode usar a diretiva ‘opens’ para permitir acesso reflexivo a pacotes, por exemplo, para bibliotecas e frameworks como Spring e Hibernate:
requires com.example.util;
opens com.example.myapp.internal to some.framework;
}
Serviços e provedores
Java Modules também suportam um mecanismo de serviços para facilitar a implementação de padrões de design como Inversão de Controle (IoC).
Definição de serviço:
exports com.example.util;
provides com.example.util.MyService with com.example.util.MyServiceImpl;
}
Uso do serviço:
requires com.example.util;
uses com.example.util.MyService;
}
No código do cliente, você pode obter um instância do serviço usando o ‘ServiceLoader’:
MyService service = serviceLoader.findFirst().orElseThrow();
Conclusão
O sistema de módulos em Java oferece uma maneira poderosa e flexível de organizar o código, controlar dependências e melhorar a segurança das aplicações. Ele é especialmente útil para grandes projetos que podem se beneficiar de uma estrutura modularizada. Ao entender e aplicar os conceitos de módulos, você pode construir aplicações Java mais robustas e manuteníveis.