Google Guice - Guia rápido
Guice é uma estrutura de injeção de dependência baseada em Java e de código aberto. É silencioso e leve e é ativamente desenvolvido / gerenciado pelo Google.
Injeção de dependência
Cada aplicativo baseado em Java possui alguns objetos que funcionam juntos para apresentar o que o usuário final vê como um aplicativo funcional. Ao escrever um aplicativo Java complexo, as classes do aplicativo devem ser o mais independentes possível de outras classes Java para aumentar a possibilidade de reutilizar essas classes e testá-las independentemente de outras classes durante o teste de unidade. A injeção de dependência (ou às vezes chamada de fiação) ajuda a colar essas classes e, ao mesmo tempo, mantê-las independentes.
Considere que você tem um aplicativo que possui um componente de editor de texto e deseja fornecer uma verificação ortográfica. Seu código padrão seria mais ou menos assim -
public class TextEditor {
private SpellChecker spellChecker;
public TextEditor() {
spellChecker = new SpellChecker();
}
}
O que fizemos aqui foi criar uma dependência entre o TextEditor e o SpellChecker. Em um cenário de inversão de controle, em vez disso, faríamos algo assim -
public class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
}
Aqui, o TextEditor não deve se preocupar com a implementação do SpellChecker. O SpellChecker será implementado de forma independente e fornecido ao TextEditor no momento da instanciação do TextEditor.
Dependency Injection using Guice (Binding)
A injeção de dependência é controlada pelo Guice Bindings. Guice usa ligações para mapear os tipos de objetos para suas implementações reais. Essas ligações são definidas como um módulo. Um módulo é uma coleção de ligações, conforme mostrado abaixo:
public class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
/*
* Bind SpellChecker binding to WinWordSpellChecker implementation
* whenever spellChecker dependency is used.
*/
bind(SpellChecker.class).to(WinWordSpellChecker.class);
}
}
O Módulo é o bloco de construção central para um injetor que é o construtor de gráfico de objeto do Guice. O primeiro passo é criar um injetor e então podemos usar o injetor para pegar os objetos.
public static void main(String[] args) {
/*
* Guice.createInjector() takes Modules, and returns a new Injector
* instance. This method is to be called once during application startup.
*/
Injector injector = Guice.createInjector(new TextEditorModule());
/*
* Build object using injector
*/
TextEditor textEditor = injector.getInstance(TextEditor.class);
}
No exemplo acima, o gráfico do objeto da classe TextEditor é construído pelo Guice e este gráfico contém o objeto TextEditor e sua dependência como objeto WinWordSpellChecker.
Configuração de ambiente local
Se você ainda deseja configurar seu ambiente para a linguagem de programação Java, esta seção o orienta sobre como fazer download e configurar o Java em sua máquina. Siga as etapas mencionadas abaixo para configurar o ambiente.
Java SE está disponível gratuitamente no link Download Java . Portanto, você baixa uma versão com base em seu sistema operacional.
Siga as instruções para baixar o Java e executar o .exepara instalar o Java em sua máquina. Depois de instalar o Java em sua máquina, você precisará definir variáveis de ambiente para apontar para os diretórios de instalação corretos -
Configurando o caminho para Windows 2000 / XP
Estamos assumindo que você instalou o Java no diretório c: \ Arquivos de programas \ java \ jdk -
Clique com o botão direito em 'Meu Computador' e selecione 'Propriedades'.
Clique no botão 'Variáveis de ambiente' na guia 'Avançado'.
Agora, altere a variável 'Path' para que também contenha o caminho para o executável Java. Exemplo, se o caminho está definido atualmente para 'C: \ WINDOWS \ SYSTEM32', altere seu caminho para 'C: \ WINDOWS \ SYSTEM32; c: \ Arquivos de programas \ java \ jdk \ bin'.
Configurando o Caminho para Windows 95/98 / ME
Estamos assumindo que você instalou o Java no diretório c: \ Arquivos de programas \ java \ jdk -
Edite o arquivo 'C: \ autoexec.bat' e adicione a seguinte linha no final - 'SET PATH =% PATH%; C: \ Arquivos de programas \ java \ jdk \ bin'
Configurando o caminho para Linux, UNIX, Solaris, FreeBSD
A variável de ambiente PATH deve ser definida para apontar para onde os binários Java foram instalados. Consulte a documentação do shell se tiver problemas para fazer isso.
Por exemplo, se você usar bash como seu shell, então você adicionaria a seguinte linha ao final de seu '.bashrc: export PATH = / path / to / java: $ PATH'
Editores Java populares
Para escrever seus programas Java, você precisa de um editor de texto. Existem muitos IDEs sofisticados disponíveis no mercado. Mas, por agora, você pode considerar um dos seguintes -
Notepad - Na máquina Windows você pode usar qualquer editor de texto simples como o Notepad (recomendado para este tutorial), TextPad.
Netbeans - É um IDE Java de código aberto e gratuito que pode ser baixado de https://www.netbeans.org/index.html.
Eclipse - Também é um IDE Java desenvolvido pela comunidade de código aberto eclipse e pode ser baixado de https://www.eclipse.org/.
Ambiente Google Guice
Baixe a versão mais recente do Google Guice e os arquivos jar relacionados.
Google Guice 4.0
AOP Alliance 1.0
Goiaba 16.0.1
javax.inject 1.0
No momento de escrever este tutorial, nós os copiamos para a pasta C: \> Google.
SO | Nome do arquivo |
---|---|
janelas | guice-4.1.0.jar; aopalliance-1.0.jar; guava-16.0.1.jar; javax.inject-1.jar |
Linux | guice-4.1.0.jar; aopalliance-1.0.jar; guava-16.0.1.jar; javax.inject-1.jar |
Mac | guice-4.1.0.jar; aopalliance-1.0.jar; guava-16.0.1.jar; javax.inject-1.jar |
Definir variável CLASSPATH
Colocou o CLASSPATHvariável de ambiente para apontar para o local do jar Guice. Supondo que você tenha armazenado Guice e jars relacionados na pasta do Google em vários sistemas operacionais da seguinte forma.
SO | Resultado |
---|---|
janelas | Defina a variável de ambiente CLASSPATH como% CLASSPATH%; C: \ Google \ guice-4.1.0.jar; C: \ Google \ aopalliance-1.0.jar; C: \ Google \ guava-16.0.1.jar; C: \ Google \ javax.inject-1.jar;.; |
Linux | export CLASSPATH = $ CLASSPATH: Google / guice-4.1.0.jar: Google / aopalliance-1.0.jar: Google / guava-16.0.1.jar: Google / javax.inject-1.jar :. |
Mac | export CLASSPATH = $ CLASSPATH: Google / guice-4.1.0.jar: Google / aopalliance-1.0.jar: Google / guava-16.0.1.jar: Google / javax.inject-1.jar :. |
Vamos criar um aplicativo de amostra baseado em console onde demonstraremos a injeção de dependência usando o mecanismo de ligação Guice passo a passo.
Etapa 1: Criar interface
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
Etapa 2: Criar Implementação
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
Etapa 3: Criar Módulo de Ligações
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
}
}
Etapa 4: criar classe com dependência
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
Etapa 5: Criar injetor
Injector injector = Guice.createInjector(new TextEditorModule());
Etapa 6: obtenha o objeto com dependência preenchida.
TextEditor editor = injector.getInstance(TextEditor.class);
Etapa 7: use o objeto.
editor.makeSpellCheck();
Exemplo Completo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
Inside checkSpelling.
Em ligações vinculadas, Guice mapeia um tipo para sua implementação. No exemplo abaixo, mapeamos a interface SpellChecker com sua implementação SpellCheckerImpl.
bind(SpellChecker.class).to(SpellCheckerImpl.class);
Também podemos mapear a classe concreta para sua subclasse. Veja o exemplo abaixo:
bind(SpellCheckerImpl.class).to(WinWordSpellCheckerImpl.class);
Aqui nós acorrentamos as amarras. Vamos ver o resultado em um exemplo completo.
Exemplo Completo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
bind(SpellCheckerImpl.class).to(WinWordSpellCheckerImpl.class);
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
//subclass of SpellCheckerImpl
class WinWordSpellCheckerImpl extends SpellCheckerImpl{
@Override
public void checkSpelling() {
System.out.println("Inside WinWordSpellCheckerImpl.checkSpelling." );
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
Inside WinWordSpellCheckerImpl.checkSpelling.
Como podemos vincular um tipo com sua implementação. No caso de desejarmos mapear um tipo com várias implementações, também podemos criar anotações personalizadas. Veja o exemplo abaixo para entender o conceito.
Crie uma anotação de ligação
@BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
@interface WinWord {}
@BindingAnnotation - Marca a anotação como anotação de ligação.
@Target - Marcas de aplicabilidade de anotação.
@Retention - Marca a disponibilidade de anotação como tempo de execução.
Mapeamento usando anotação de ligação
bind(SpellChecker.class).annotatedWith(WinWord.class).to(WinWordSpellCheckerImpl.class);
Injetar usando anotação de ligação
@Inject
public TextEditor(@WinWord SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
Exemplo Completo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import java.lang.annotation.Target;
import com.google.inject.AbstractModule;
import com.google.inject.BindingAnnotation;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
@BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
@interface WinWord {}
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(@WinWord SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).annotatedWith(WinWord.class)
.to(WinWordSpellCheckerImpl.class);
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
//subclass of SpellCheckerImpl
class WinWordSpellCheckerImpl extends SpellCheckerImpl{
@Override
public void checkSpelling() {
System.out.println("Inside WinWordSpellCheckerImpl.checkSpelling." );
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
Inside WinWordSpellCheckerImpl.checkSpelling.
O Guice também fornece outra maneira de mapear ligações sem criar uma anotação personalizada. Isso permite usando a anotação @Named.
Mapeamento usando anotação nomeada
bind(SpellChecker.class).annotatedWith(Names.named("OpenOffice")).to(OpenOfficeWordSpellCheckerImpl.class);
Injetar usando a anotação @Named
@Inject
public TextEditor(@Named("OpenOffice") SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
Exemplo Completo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(@Named("OpenOffice") SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).annotatedWith(Names.named("OpenOffice"))
.to(OpenOfficeWordSpellCheckerImpl.class);
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
//subclass of SpellCheckerImpl
class OpenOfficeWordSpellCheckerImpl extends SpellCheckerImpl{
@Override
public void checkSpelling() {
System.out.println("Inside OpenOfficeWordSpellCheckerImpl.checkSpelling." );
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
Inside OpenOfficeWordSpellCheckerImpl.checkSpelling.
O Guice fornece uma maneira de criar ligações com objetos de valor ou constantes. Considere o caso em que queremos configurar o url JDBC.
Injetar usando a anotação @Named
@Inject
public void connectDatabase(@Named("JBDC") String dbUrl) {
//...
}
Isso pode ser obtido usando o método toInstance ().
bind(String.class).annotatedWith(Names.named("JBDC")).toInstance("jdbc:mysql://localhost:5326/emp");
Exemplo Completo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeConnection();
}
}
class TextEditor {
private String dbUrl;
@Inject
public TextEditor(@Named("JDBC") String dbUrl) {
this.dbUrl = dbUrl;
}
public void makeConnection(){
System.out.println(dbUrl);
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(String.class)
.annotatedWith(Names.named("JDBC"))
.toInstance("jdbc:mysql://localhost:5326/emp");
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
jdbc:mysql://localhost:5326/emp
O Guice fornece uma maneira de criar ligações com objetos complexos usando o método @provides.
@Provides
public SpellChecker provideSpellChecker(){
String dbUrl = "jdbc:mysql://localhost:5326/emp";
String user = "user";
int timeout = 100;
SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
return SpellChecker;
}
Esse método faz parte do Binding Module e fornece o objeto complexo a ser mapeado. Veja o exemplo completo abaixo.
Exemplo Completo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provides;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {}
@Provides
public SpellChecker provideSpellChecker(){
String dbUrl = "jdbc:mysql://localhost:5326/emp";
String user = "user";
int timeout = 100;
SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
return SpellChecker;
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
private String dbUrl;
private String user;
private Integer timeout;
@Inject
public SpellCheckerImpl(String dbUrl,
String user,
Integer timeout){
this.dbUrl = dbUrl;
this.user = user;
this.timeout = timeout;
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
System.out.println(user);
System.out.println(timeout);
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
Inside checkSpelling.
jdbc:mysql://localhost:5326/emp
user
100
Conforme o método @provides se torna mais complexo, esses métodos podem ser movidos para classes separadas usando a interface do Provedor.
class SpellCheckerProvider implements Provider<SpellChecker>{
@Override
public SpellChecker get() {
String dbUrl = "jdbc:mysql://localhost:5326/emp";
String user = "user";
int timeout = 100;
SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
return SpellChecker;
}
}
A próxima etapa é mapear o provedor para o tipo.
bind(SpellChecker.class).toProvider(SpellCheckerProvider.class);
Veja o exemplo completo abaixo.
Exemplo Completo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class)
.toProvider(SpellCheckerProvider.class);
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
private String dbUrl;
private String user;
private Integer timeout;
@Inject
public SpellCheckerImpl(String dbUrl,
String user,
Integer timeout){
this.dbUrl = dbUrl;
this.user = user;
this.timeout = timeout;
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
System.out.println(user);
System.out.println(timeout);
}
}
class SpellCheckerProvider implements Provider<SpellChecker>{
@Override
public SpellChecker get() {
String dbUrl = "jdbc:mysql://localhost:5326/emp";
String user = "user";
int timeout = 100;
SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
return SpellChecker;
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
Inside checkSpelling.
jdbc:mysql://localhost:5326/emp
user
100
O Guice fornece uma maneira de criar ligações com o construtor específico de um objeto usando o método toConstructor ().
@Override
protected void configure() {
try {
bind(SpellChecker.class)
.toConstructor(SpellCheckerImpl.class.getConstructor(String.class));
} catch (NoSuchMethodException | SecurityException e) {
System.out.println("Required constructor missing");
}
}
Veja o exemplo completo abaixo.
Exemplo Completo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
try {
bind(SpellChecker.class)
.toConstructor(SpellCheckerImpl.class.getConstructor(String.class));
} catch (NoSuchMethodException | SecurityException e) {
System.out.println("Required constructor missing");
}
bind(String.class)
.annotatedWith(Names.named("JDBC"))
.toInstance("jdbc:mysql://localhost:5326/emp");
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
private String dbUrl;
public SpellCheckerImpl(){}
public SpellCheckerImpl(@Named("JDBC") String dbUrl){
this.dbUrl = dbUrl;
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
Inside checkSpelling.
jdbc:mysql://localhost:5326/emp
Guice fornece ligação embutida para a classe java.util.logging.Logger . O nome do Logger é automaticamente definido como o nome da classe na qual o Logger é injetado. Veja o exemplo abaixo.
Exemplo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import java.util.logging.Logger;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private Logger logger;
@Inject
public TextEditor( Logger logger) {
this.logger = logger;
}
public void makeSpellCheck(){
logger.info("In TextEditor.makeSpellCheck() method");
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
Dec 20, 2017 12:51:05 PM TextEditor makeSpellCheck
INFO: In TextEditor.makeSpellCheck() method
Como as ligações são definidas no Módulo Binding, Guice as usa sempre que precisa injetar dependências. Caso as associações não estejam presentes, ele pode tentar criar associações just-in-time. As ligações presentes no módulo de ligação são chamadas de ligações explícitas e têm maior precedência, enquanto as ligações just-in-time são chamadas de ligações implícitas. Se ambos os tipos de ligações estiverem presentes, ligações explícitas serão consideradas para mapeamento.
A seguir estão os exemplos de três tipos de vinculações Just-in-time.
Tipo de ligação | Descrição |
---|---|
Construtores injetáveis | Construtores não privados e sem argumento são elegíveis para associações just-in-time. Outra maneira é anotar um construtor com a anotação @Inject. |
Anotação @ImplementatedBy | A anotação @ImplementatedBy informa o guia sobre a classe de implementação. Nesse caso, nenhuma ligação é necessária no Módulo de vinculação. |
Anotação @ProvidedBy | A anotação @ProvidedBy informa ao guia sobre o provedor da classe de implementação. Nesse caso, nenhuma ligação é necessária no Módulo de vinculação. |
Construtores não privados e sem argumento são elegíveis para associações just-in-time. Outra maneira é anotar um construtor com a anotação @Inject. Veja o exemplo:
Exemplo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
bind(String.class)
.annotatedWith(Names.named("JDBC"))
.toInstance("jdbc:mysql://localhost:5326/emp");
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Inject @Named("JDBC")
private String dbUrl;
public SpellCheckerImpl(){}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
Inside checkSpelling.
jdbc:mysql://localhost:5326/emp
A anotação @ImplementatedBy informa o guia sobre a classe de implementação. Nesse caso, nenhuma ligação é necessária no Módulo de vinculação. Veja o exemplo:
Exemplo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(String.class)
.annotatedWith(Names.named("JDBC"))
.toInstance("jdbc:mysql://localhost:5326/emp");
}
}
@ImplementedBy(SpellCheckerImpl.class)
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Inject @Named("JDBC")
private String dbUrl;
public SpellCheckerImpl(){}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
Inside checkSpelling.
jdbc:mysql://localhost:5326/emp
A anotação @ProvidedBy informa ao guia sobre o provedor da classe de implementação. Nesse caso, nenhuma ligação é necessária no Módulo de vinculação. Veja o exemplo:
Exemplo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.ProvidedBy;
import com.google.inject.Provider;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
}
}
@ProvidedBy(SpellCheckerProvider.class)
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
private String dbUrl;
private String user;
private Integer timeout;
@Inject
public SpellCheckerImpl(String dbUrl,
String user,
Integer timeout){
this.dbUrl = dbUrl;
this.user = user;
this.timeout = timeout;
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
System.out.println(user);
System.out.println(timeout);
}
}
class SpellCheckerProvider implements Provider<SpellChecker>{
@Override
public SpellChecker get() {
String dbUrl = "jdbc:mysql://localhost:5326/emp";
String user = "user";
int timeout = 100;
SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
return SpellChecker;
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
Inside checkSpelling.
jdbc:mysql://localhost:5326/emp
user
100
A injeção é um processo de injeção de dependência em um objeto. A injeção de construtor é bastante comum. Nesse processo, a dependência é injetada como argumento para o construtor. Veja o exemplo abaixo.
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
Inside checkSpelling.
A injeção é um processo de injeção de dependência em um objeto. A injeção de método é usada para definir o objeto de valor como dependência do objeto. Veja o exemplo abaixo.
Exemplo
Crie uma classe java chamada GuiceTester.
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(String.class)
.annotatedWith(Names.named("JDBC"))
.toInstance("jdbc:mysql://localhost:5326/emp");
}
}
@ImplementedBy(SpellCheckerImpl.class)
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
private String dbUrl;
public SpellCheckerImpl(){}
@Inject
public void setDbUrl(@Named("JDBC") String dbUrl){
this.dbUrl = dbUrl;
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
Inside checkSpelling.
jdbc:mysql://localhost:5326/emp
A injeção é um processo de injeção de dependência em um objeto. A injeção de campo é usada para definir o objeto de valor como dependência do campo de um objeto. Veja o exemplo abaixo.
Exemplo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(String.class)
.annotatedWith(Names.named("JDBC"))
.toInstance("jdbc:mysql://localhost:5326/emp");
}
}
@ImplementedBy(SpellCheckerImpl.class)
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Inject @Named("JDBC")
private String dbUrl;
public SpellCheckerImpl(){}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
Inside checkSpelling.
jdbc:mysql://localhost:5326/emp
A injeção é um processo de injeção de dependência em um objeto. A injeção opcional significa injetar a dependência, se houver. As injeções de método e campo podem ser opcionalmente dependentes e devem ter algum valor padrão se a dependência não estiver presente. Veja o exemplo abaixo.
Exemplo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.name.Named;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor( SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {}
}
@ImplementedBy(SpellCheckerImpl.class)
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
private String dbUrl = "jdbc:mysql://localhost:5326/emp";
public SpellCheckerImpl(){}
@Inject(optional=true)
public void setDbUrl(@Named("JDBC") String dbUrl){
this.dbUrl = dbUrl;
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
System.out.println(dbUrl);
}
}
Resultado
Compile e execute o arquivo, você verá a seguinte saída.
Inside checkSpelling.
jdbc:mysql://localhost:5326/emp
A injeção é um processo de injeção de dependência em um objeto. O método e as injeções de campo podem ser usados para inicializar usando o objeto existente usando o método injector.injectMembers () . Veja o exemplo abaixo.
Exemplo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Injector;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
SpellChecker spellChecker = new SpellCheckerImpl();
injector.injectMembers(spellChecker);
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public void setSpellChecker(SpellChecker spellChecker){
this.spellChecker = spellChecker;
}
public TextEditor() { }
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
}
}
@ImplementedBy(SpellCheckerImpl.class)
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
public SpellCheckerImpl(){}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
Compile e execute o arquivo, você verá a seguinte saída.
Inside checkSpelling.
Guice retorna uma nova instância sempre que fornece um valor como seu comportamento padrão. É configurável por meio de escopos. A seguir estão os escopos que o Guice suporta:
@Singleton- Única instância para o tempo de vida do aplicativo. O objeto @Singleton precisa ser threadsafe.
@SessionScoped- Instância única para uma sessão específica do aplicativo da web. O objeto @SessionScoped precisa ser threadsafe.
@RequestScoped- Única instância para uma solicitação específica do aplicativo da web. O objeto @RequestScoped não precisa ser threadsafe.
Maneira de aplicar escopos.
A seguir estão as maneiras de aplicar escopos.
No nível da classe
@Singleton
class SpellCheckerImpl implements SpellChecker {
public SpellCheckerImpl(){}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
No nível de configuração
bind(SpellChecker.class).to(SpellCheckerImpl.class).in(Singleton.class);
No nível do método
@Provides @Singleton
public SpellChecker provideSpellChecker(){
String dbUrl = "jdbc:mysql://localhost:5326/emp";
String user = "user";
int timeout = 100;
SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout);
return SpellChecker;
}
Exemplo
Vamos ver o Escopo no nível da classe em ação.
Resultado com anotação @Singleton
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
SpellChecker spellChecker = new SpellCheckerImpl();
injector.injectMembers(spellChecker);
TextEditor editor = injector.getInstance(TextEditor.class);
System.out.println(editor.getSpellCheckerId());
TextEditor editor1 = injector.getInstance(TextEditor.class);
System.out.println(editor1.getSpellCheckerId());
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public void setSpellChecker(SpellChecker spellChecker){
this.spellChecker = spellChecker;
}
public TextEditor() { }
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
public double getSpellCheckerId(){
return spellChecker.getId();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
}
}
interface SpellChecker {
public double getId();
public void checkSpelling();
}
@Singleton
class SpellCheckerImpl implements SpellChecker {
double id;
public SpellCheckerImpl(){
id = Math.random();
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
@Override
public double getId() {
return id;
}
}
Compile e execute o arquivo, você verá a seguinte saída.
0.3055839187063575
0.3055839187063575
Resultado sem anotação @Singleton
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
SpellChecker spellChecker = new SpellCheckerImpl();
injector.injectMembers(spellChecker);
TextEditor editor = injector.getInstance(TextEditor.class);
System.out.println(editor.getSpellCheckerId());
TextEditor editor1 = injector.getInstance(TextEditor.class);
System.out.println(editor1.getSpellCheckerId());
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public void setSpellChecker(SpellChecker spellChecker){
this.spellChecker = spellChecker;
}
public TextEditor() { }
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
public double getSpellCheckerId(){
return spellChecker.getId();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
}
}
interface SpellChecker {
public double getId();
public void checkSpelling();
}
class SpellCheckerImpl implements SpellChecker {
double id;
public SpellCheckerImpl(){
id = Math.random();
}
@Override
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
@Override
public double getId() {
return id;
}
}
Compile e execute o arquivo, você verá a seguinte saída.
0.556007079571739
0.22095011760351602
Google Guice - AOP
AOP, programação orientada a Aspectos envolve quebrar a lógica do programa em partes distintas chamadas de preocupações. As funções que abrangem vários pontos de um aplicativo são chamadas de interesses transversais e esses interesses transversais são conceitualmente separados da lógica de negócios do aplicativo. Existem vários bons exemplos comuns de aspectos como registro, auditoria, transações declarativas, segurança, armazenamento em cache, etc.
A principal unidade de modularidade em OOP é a classe, enquanto em AOP a unidade de modularidade é o aspecto. A injeção de dependência ajuda a desacoplar seus objetos de aplicativo uns dos outros e o AOP ajuda a desacoplar interesses transversais dos objetos que eles afetam. AOP é como gatilhos em linguagens de programação como Perl, .NET, Java e outras. O Guice fornece interceptores para interceptar um aplicativo. Por exemplo, quando um método é executado, você pode adicionar funcionalidade extra antes ou depois da execução do método.
Aulas importantes
Matcher- Matcher é uma interface para aceitar ou rejeitar um valor. No Guice AOP, precisamos de dois matchers: um para definir quais classes participam e outro para os métodos dessas classes.
MethodInterceptor- MethodInterceptors são executados quando um método de correspondência é chamado. Eles podem inspecionar a chamada: o método, seus argumentos e a instância de recebimento. Podemos realizar lógica cruzada e então delegar ao método subjacente. Finalmente, podemos inspecionar o valor de retorno ou exceção e retornar.
Exemplo
Crie uma classe java chamada GuiceTester.
GuiceTester.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.matcher.Matchers;
public class GuiceTester {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TextEditorModule());
TextEditor editor = injector.getInstance(TextEditor.class);
editor.makeSpellCheck();
}
}
class TextEditor {
private SpellChecker spellChecker;
@Inject
public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void makeSpellCheck(){
spellChecker.checkSpelling();
}
}
//Binding Module
class TextEditorModule extends AbstractModule {
@Override
protected void configure() {
bind(SpellChecker.class).to(SpellCheckerImpl.class);
bindInterceptor(Matchers.any(),
Matchers.annotatedWith(CallTracker.class),
new CallTrackerService());
}
}
//spell checker interface
interface SpellChecker {
public void checkSpelling();
}
//spell checker implementation
class SpellCheckerImpl implements SpellChecker {
@Override @CallTracker
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD)
@interface CallTracker {}
class CallTrackerService implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Before " + invocation.getMethod().getName());
Object result = invocation.proceed();
System.out.println("After " + invocation.getMethod().getName());
return result;
}
}
Compile e execute o arquivo, você verá a seguinte saída.
Before checkSpelling
Inside checkSpelling.
After checkSpelling