Professional Documents
Culture Documents
Página 1
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
Conteúdo
Introdução
Instalação
Anotações de Lombok
o @Getter e @Setter
o @NonNull
o @Para sequenciar
o @EqualsAndHashCode
o @Dados
o @Limpar
o @ Sincronizado
o @SneakyThrows
Custos e Benefícios
o O que estamos perdendo?
o Limitações
o Controvérsia
Resumo
Referências
Página 2
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
Introdução
Embora não seja incomum que as anotações sejam usadas para indicar o uso, para
implementar ligações ou mesmo para gerar código usado por frameworks, eles
geralmente não são usados para a geração de código que é diretamente utilizado
pela aplicação. Isso é em parte porque, assim, exigiria que as anotações fossem
processadas ansiosamente no tempo de desenvolvimento. Projeto Lombok faz
exatamente isso. Ao se integrar ao IDE, o Project Lombok pode injetar o código que
está imediatamente disponível para o desenvolvedor. Por exemplo, simplesmente
adicionando a @Dataanotação a uma classe de dados, conforme abaixo, resulta em
vários novos métodos no IDE:
Página 3
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
Instalação
Projeto Lombok está disponível como um único arquivo jar no site do projeto . Inclui
as APIs para desenvolvimento como instalador para integração IDE. Na maioria dos
sistemas, basta clicar duas vezes no arquivo jar para iniciar o instalador. Se o
sistema não estiver configurado para iniciar arquivos de jar corretamente, ele
também pode ser executado a partir da linha de comando da seguinte maneira:
O arquivo jar ainda precisa ser incluído no classpath de qualquer projeto que usará
as anotações do Projeto Lombok. Os usuários do Maven podem incluir o Lombok
como uma dependência ao adicionar isso ao arquivo pom.xml do projeto:
Página 4
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
<dependências>
<dependência>
<groupId> org.projectlombok </ groupId>
<artifactId> lombok </ artifactId>
<versão> 1.16.16 </ version>
</ dependency>
</ dependencies>
<repositórios>
<repositório>
<id> projectlombok.org </ id>
<url> http://projectlombok.org/mavenrepo </ url>
</ repositório>
</ repositories>
Anotações de Lombok
Não é incomum que um projeto Java típico consiga centenas de linhas de código
para o campo necessário para definir classes de dados simples. Essas classes
geralmente contêm uma série de campos, getters e setters para esses campos, bem
como equalse hashCodeimplementações. Nos cenários mais simples, o Project
Lombok pode reduzir essas classes para os campos necessários e uma
única @Dataanotação.
@Getter e @Setter
Página 5
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
@NonNull
@NonNull
Lista privada <Pessoa> membros;
@NonNull
lista pública <Pessoa> getMembers () {
retornar membros;
}
Página 6
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
@Para sequenciar
Esta anotação gera uma implementação do toString método. Por padrão, qualquer
campo não-estático será incluído na saída do método em pares nome-valor. Se
desejar, a inclusão dos nomes de propriedades na saída pode ser suprimida
definindo o parâmetro de anotação includeFieldNamespara false.
@ java.lang.Override
public java.lang.String toString () {
retornar "Foo (super =" + super.toString () +
", someBoolean =" + someBoolean +
", someStringField =" + someStringField + ")";
}
}
@EqualsAndHashCode
Página 7
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
gerada. Pode-se usar o ofparâmetro para listar apenas esses campos devem ser
considerados.
Enum Gender {
/ * public static final * / Male / * = new Gender () * /,
/ * public static final * / Female / * = new Gender () * /;
}
@NonNull
Nome da Cadeia de caracteres privada;
@NonNull
gênero de gênero privado;
Página 8
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
@ java.lang.Override
público booleano igual (final java.lang.Object o) {
se (o == isto) retornar verdadeiro;
se (o == nulo) retornar falso;
se (o.getClass ()! = this.getClass ()) retornar falso;
se (! super.equals (o)) retornar falso;
Final Pessoa outra = (Pessoa) o;
se (this.name == null? other.name! = null:! this.name.equals (other.name))
return false;
se (this.gender == null? other.gender! = null:! this.gender.equals
(other.gender)) return false;
se (this.ssn == null? other.ssn! = null:! this.ssn.equals (other.ssn)) return
false;
retornar verdadeiro;
}
@ java.lang.Override
public int hashCode () {
final int PRIME = 31;
int resultado = 1;
resultado = resultado * PRIME + super.hashCode ();
resultado = resultado * PRIME + (this.name == null? 0: this.name.hashCode
());
resultado = resultado * PRIME + (this.gender == null? 0:
this.gender.hashCode ());
resultado = resultado * PRIME + (this.ssn == null? 0: this.ssn.hashCode ());
resultado de retorno;
}
}
@Dados
Página 9
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
geração do método padrão, anote a classe, o campo ou o método com uma das
outras anotações do Lombok e especifique os valores dos parâmetros necessários
para alcançar o efeito desejado.
@Datafornece uma opção de parâmetro único que pode ser usada para gerar um
método estático de fábrica. Definir o valor do staticConstructorparâmetro para o
nome do método desejado fará com que o Lombok faça o construtor gerado ser
privado e exponha um método estático de fábrica do nome.
Página 10
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
this.employees = employees;
}
@ java.lang.Override
público booleano igual (final java.lang.Object o) {
se (o == isto) retornar verdadeiro;
se (o == nulo) retornar falso;
se (o.getClass ()! = this.getClass ()) retornar falso;
Empresa final outra = (Empresa) o;
se (this.founder == null? other.founder! = null:! this.founder.equals
(other.founder)) return false;
se (this.name == null? other.name! = null:! this.name.equals (other.name))
return false;
se (this.employees == null? other.employees! = null:! this.employees.equals
(other.employees)) return false;
retornar verdadeiro;
}
@ java.lang.Override
public int hashCode () {
final int PRIME = 31;
int resultado = 1;
resultado = resultado * PRIME + (this.founder == null? 0:
this.founder.hashCode ());
resultado = resultado * PRIME + (this.name == null? 0: this.name.hashCode
());
resultado = resultado * PRIME + (this.employees == null? 0:
this.employees.hashCode ());
resultado de retorno;
}
@ java.lang.Override
public java.lang.String toString () {
retornar "Empresa (founder =" + founder + ", name =" + name + ",
employees =" + employees + ")";
}
}
@Limpar
A @Cleanupanotação pode ser usada para garantir que os recursos alocados sejam
liberados. Quando uma variável local é anotada @Cleanup, qualquer código
subsequente é enrolado em um try/finallybloco que garante que o método de
limpeza seja chamado no final do escopo atual. Por padrão, @Cleanup assume que o
método de limpeza é chamado de "fechar", como com os fluxos de entrada e
saída. No entanto, um nome de método diferente pode ser fornecido
ao valueparâmetro da anotação . Somente os métodos de limpeza que não possuem
parâmetros podem ser usados com esta anotação.
Página 11
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
@ Sincronizado
Página 12
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
@ Sincronizado
public String synchronizedFormat (data data) {
retornar format.format (data);
}
@SneakyThrows
Página 13
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
@SneakyThrows
public void testSneakyThrows () {
lança nova IllegalAccessException ();
}
Custos e Benefícios
Tal como acontece com qualquer escolha tecnológica, existem efeitos positivos e
negativos do uso do Projeto Lombok. A incorporação das anotações do Lombok em
um projeto pode reduzir muito o número de linhas do código de referência que são
geradas no IDE ou escritas manualmente. Isso resulta em despesas de manutenção
reduzidas, menos erros e classes mais legíveis.
Isso não quer dizer que não há desvantagens para o uso de anotações do Projeto
Lombok em seu projeto. Projeto Lombok é em grande parte destinado a preencher
lacunas na linguagem Java. Como tal, existe a possibilidade de mudanças no idioma
que impedem o uso das anotações de Lombok, como a adição de suporte de
propriedade de primeira classe. Além disso, quando usado em combinação com
estruturas de mapeamento de objeto-relacionamento baseadas em anotação (ORM),
o número de anotações em classes de dados pode começar a ser complicado. Isso é
Página 14
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
pacote com.ociweb.jnb.lombok;
importar java.util.Date;
importar lombok.Data;
importar lombok.EqualsAndHashCode;
importar lombok.NonNull;
@Dados
@EqualsAndHashCode (exclude = {"endereço", "cidade", "estado", "zip"})
classe pública Pessoa {
enum Sexo {Masculino, Feminino}
Página 15
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
pacote com.ociweb.jnb.lombok;
importar java.util.Date;
importar lombok.NonNull;
Enum Gender {
/ * public static final * / Male / * = new Gender () * /,
/ * public static final * / Female / * = new Gender () * /;
}
@NonNull
Private String firstName;
@NonNull
private String lastName;
@NonNull
final privado gênero gênero;
@NonNull
Data final da data final privada;
private String ssn;
endereço de string privado;
cidade de Cadeia privada;
estado String privado;
Private String zip;
pessoa pública (@NonNull final String firstName, @NonNull final String lastName,
@NonNull final Sexo gênero, @NonNull final Data dateOfBirth) {
se (firstName == null)
lance nova java.lang.NullPointerException ("firstName");
se (lastName == null)
lance nova java.lang.NullPointerException ("lastName");
se (gênero == nulo)
lance nova java.lang.NullPointerException ("gender");
se (dateOfBirth == null)
lance nova java.lang.NullPointerException ("dateOfBirth");
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.dateOfBirth = dateOfBirth;
}
Página 16
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
@NonNull
public String getFirstName () {
retornar primeiro Nome;
}
@NonNull
public String getLastName () {
retornar por último;
}
@NonNull
público Sexo getGender () {
retornar gênero;
}
@NonNull
public Data getDateOfBirth () {
data de retornoOfBirth;
}
Página 17
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
@ java.lang.Override
public java.lang.String toString () {
retornar "Person (firstName =" + firstName + ", lastName =" + lastName +
", gender =" + gender + ", dateOfBirth =" + dateOfBirth +
", ssn =" + ssn + ", endereço =" + endereço + ", cidade =" + cidade +
", state =" + state + ", zip =" + zip + ")";
}
@ java.lang.Override
público booleano igual (final java.lang.Object o) {
se (o == isto) retornar verdadeiro;
se (o == nulo) retornar falso;
se (o.getClass ()! = this.getClass ()) retornar falso;
Final Pessoa outra = (Pessoa) o;
se (this.firstName == null
? other.firstName! = null
:! this.firstName.equals (other.firstName))
retorna falso;
se (this.lastName == null
? other.lastName! = null
:! this.lastName.equals (other.lastName))
retorna falso;
se (this.gender == null
? other.gender! = null
:! this.gender.equals (other.gender))
retorna falso;
se (this.dateOfBirth == null
? other.dateOfBirth! = null
Página 18
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
:! this.dateOfBirth.equals (other.dateOfBirth))
retorna falso;
se (this.ssn == null
? other.ssn! = null
:! this.ssn.equals (other.ssn))
retorna falso;
retornar verdadeiro;
}
@ java.lang.Override
public int hashCode () {
final int PRIME = 31;
int resultado = 1;
resultado = resultado * PRIME +
(this.firstName == null? 0: this.firstName.hashCode ());
resultado = resultado * PRIME +
(this.lastName == null? 0: this.lastName.hashCode ());
resultado = resultado * PRIME +
(this.gender == null? 0: this.gender.hashCode ());
resultado = resultado * PRIME +
(this.dateOfBirth == null? 0: this.dateOfBirth.hashCode ());
resultado = resultado * PRIME +
(this.ssn == null? 0: this.ssn.hashCode ());
resultado de retorno;
}
}
Tenha em mente que este não é apenas um código que normalmente deve ser
escrito, mas também deve ser lido ao manter os desenvolvedores. Isso significa que,
ao usar as anotações fornecidas pelo Projeto Lombok, os desenvolvedores não
precisam percorrer inúmeras linhas de código para determinar se a classe em
questão é uma classe de dados simples ou algo mais sinistro.
Limitações
Enquanto o Projeto Lombok faz algumas coisas dramáticas para tornar a vida de um
desenvolvedor mais fácil, tem suas limitações. Navegar a lista de problemas irá
iluminar rapidamente algumas das falhas atuais, a maioria das quais menor. Um
problema importante é a incapacidade de detectar os construtores de uma
superclasse. Isso significa que, se uma superclasse não possui um construtor
padrão, nenhuma subclasse não pode usar a anotação @Data sem escrever
explicitamente um construtor para fazer uso do construtor de superclasse
disponível. Como o Projeto Lombok respeita todos os métodos que combinam o
nome de um método a ser gerado, a maioria das deficiências de suas características
pode ser superada usando esta abordagem.
Controvérsia
Página 19
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
"meta" e não devem ser usadas de forma a que a base de código não pudesse ser
compilada se eles fossem removidos. Esta é certamente a situação com as anotações
do Lombok. Novos métodos resultam dessas anotações que se destinam a ser
usadas não apenas por uma estrutura, mas por outras partes da aplicação. O apoio
ao desenvolvimento do tempo do Projeto Lombok é o pão e a manteiga, mas isso
tem conseqüências, e nem o menor é o suporte limitado do IDE.
É um hack total. Usando API não pública. Casting prematuro (sabendo que um
o processador de anotação em execução no javac receberá uma instância do
JavacAnnotationProcessor,
qual é a implementação interna do AnnotationProcessor (uma interface), que
Por acaso, tem alguns métodos extras que são usados para obter o AST ao vivo).
Se você pudesse fazer o que o lombok faz com a API padrão, eu teria feito isso
dessa maneira, mas
você não pode. Ainda assim, pelo que valeu, desenvolvi o plugin do eclipse para o
eclipse v3.5
rodando no java 1.6, e sem fazer alterações que funcionou no eclipse v3.4 running
Também no java 1.5, então não é completamente frágil.
Resumo
Página 20
LOMBOK – Reduzindo o Código Boilerplate com o Projeto Lombok
Referências
Projeto Lombok -
http://projectlombok.org
Documentação API Lombok -
http://projectlombok.org/api/index.html
Lista de Problemas do Projeto Lombok -
http://code.google.com/p/projectlombok/issues/list
Use Lombok via Maven -
http://projectlombok.org/mavenrepo/index.html
Grupo Project Lombok Google -
http://groups.google.com/group/project-lombok
Revisando o Projeto Lombok ou o caminho certo para escrever uma biblioteca
-
http://www.cforcoding.com/2009/11/reviewing-project-lombok-or-right-
way.html
Morbok: extensões para o Lombok -
http://code.google.com/p/morbok
Usando o Projeto Lombok com JDeveloper -
http://kingsfleet.blogspot.com/2009/09/project-lombok-interesting-bean.html
Código de exemplo -
LombokExample.zip
Página 21
LOMBOK – Artigos e Dicas
Dependências do Maven
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.14</version>
<scope>provided</scope>
</dependency>
Anotações
Página 22
LOMBOK – Introdução ao Lombok
##Mãos à obra
###@NonNull
4 }
5 }
###@Getter @Setter
Field level
3 @Getter
Página 23
LOMBOK – Introdução ao Lombok
4 String name;
6 @Getter @Setter
7 CreatureType type;
8 }
Class level
1 @Getter @Setter
4 String name;
6 CreatureType type;
7 }
###@EqualsAndHashCode
1 @EqualsAndHashCode
Página 24
LOMBOK – Introdução ao Lombok
3 String name;
4 CreatureType type;
5 }
###@ToString
1 @ToString
3 String name;
4 CreatureType type;
5 }
###@Data
1 @Data
3 String name;
4 CreatureType type;
5 }
###@AllArgsConstructor
Página 25
LOMBOK – Introdução ao Lombok
1 @AllArgsConstructor
3 String name;
4 CreatureType type;
5 }
2 this.name = name;
3 this.type = type;
4 }
###@Slf4j
1 @Slf4j
5 log.info("Entrei no doGet");
6 }
7 }
2
org.slf4j.LoggerFactory.getLogger(CreatureResource.class);
Página 26
LOMBOK – Introdução ao Lombok
Como toda boa ferramenta, deve ser usado sem abuso. Particularmente,
eu evito usar @Data, pois não gosto de expor meus sets. Além disso,
implementações do equals e do hashcode gerados devem ser validados
através de testes unitários para garantir que o comportamento é o
esperado pelo desenvolvedor.
Página 27