- O que é interceptor?
- Passos para criação do interceptor Cronometro
- Passo 1 – Criação da nova annotation Cronometro
- Passo 2 -Criação do Interceptor
- Passo 2.1 – Declaração da classe e annotations iniciais
- Passo 2.2 – Implementação do método base
- Passo 2.3 – Inserir o código comum dentro do método base
- Passo 3 – Adicionar o interceptor no arquivo beans.xml
- Passo 4 – Utilizar a annotation nos lugares desejados
- finnaly{
Olá Pessoal, tudo bom?
No artigo de hoje vamos fazer um passo a passo da construção de um interceptor chamado Cronometro, que servirá para indicar quanto tempo um determinado método foi executado. Veja na continuação…
O que é interceptor?
Se você não sabe o que é um interceptor dá uma olhada nesse artigo.
Passos para criação do interceptor Cronometro
A primeira coisa que deve ser pensada ao criar um interceptor é quais atividades comuns ele irá realizar. No caso do Cronometro em vários trechos do código nós temos medidas de tempo, para saber se algum método está levando muito tempo para ser executado. Assim esse trecho que realiza a medição é o código comum. Ele estará presente no interceptor e não mais nos métodos.
Agora que temos a certeza de que pode ser criado um interceptor existem esses 4 passos a serem realizados:
- Criar uma annotation própria para identificar o interceptor
- Criar a classe que implementa o interceptor
- Adicionar o interceptor no arquivo beans.xml
- Utilizar a nova annotation no trecho de código desejado
Passo 1 – Criação da nova annotation Cronometro
No package desejado, por exemplo br.com.mauda.seminario.cientificos.interceptor, crie uma annotation chamada Cronometro, conforme o código abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package br.com.mauda.seminario.cientificos.interceptor; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.interceptor.InterceptorBinding; @InterceptorBinding @Target({ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) public @interface Cronometro { } |
Algumas explicações:
- A annotation @InterceptorBinding indica que essa annotation está vinculada a um interceptor.
- A annotation @Target indica em quais estruturas do java a annotation pode ser utilizada. No nosso exemplo, pode ser utilizada para anotar métodos (method) e classes (type)
- A annotation @Retention indica quando a JVM pode descartar a annotation. Existem 3 tipos, Class, Runtime e Source. Como o Java possui 3 fases de compilação, Código -> byteCodes -> Execução. Cada um desses 3 tipos está vinculado a uma fase desta. Como queremos que a annotation permaneça mesmo após a execução, escolhemos a constante RUNTIME.
Passo 2 -Criação do Interceptor
Nesse passo a classe que faz o trabalho do interceptor será criada.
Passo 2.1 – Declaração da classe e annotations iniciais
Primeiro a classe deve ser criada.
Após inserir na declaração da classe a annotation@Interceptor, a qual indica que a classe é uma interceptor para o CDI.
Por fim inserir a annotation recém criada @Cronometro.
O código abaixo mostra como ficou a classe:
1 2 3 4 5 6 7 8 9 |
package br.com.mauda.seminario.cientificos.interceptor; import javax.interceptor.Interceptor; @Interceptor @Cronometro public class CronometroInterceptor { } |
Passo 2.2 – Implementação do método base
Esse próximo sub-passo é implementar o método que irá realizar o código comum antes de chamar o método original.
O método pode ter qualquer nome, no caso aqui colocamos manage. O mais importante aqui é este possuir apenas um parâmetro do tipo InvocationContext, estar annotado com @AroundInvoke e lançar uma Exception no caso de exceções.
O código abaixo mostra como ficou a classe:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package br.com.mauda.seminario.cientificos.interceptor; import javax.interceptor.AroundInvoke; import javax.interceptor.Interceptor; import javax.interceptor.InvocationContext; @Interceptor @Cronometro public class CronometroInterceptor { @AroundInvoke public Object manage(InvocationContext ctx) throws Exception { } } |
Passo 2.3 – Inserir o código comum dentro do método base
Agora nesse sub-passo, vamos inserir o código comum dentro do método criado.
Para criar um cronometro, vamos utilizar a classe StopWatch da biblioteca Apache Commons. Iremos utilizar 4 métodos dessa classe:
- createStarted(), linha 18, o qual cria uma instância da classe já rodando a contagem do tempo
- isStarted(), linha 22, o qual verifica se o cronometro ainda está cronometrando
- stop(), linha 23, o qual para o cronometragem
- getTime(TimeUnit), linha 26, o qual recupera a quantidade de tempo de acordo com a unidade de tempo passada como parâmetro
Além disso iremos logar o tempo gasto utilizando a biblioteca Log4J conforme mostra a linha 25.
Por fim, um detalhe muito importante na linha 20. A chamada via InvocationContext ao método original, utilizando o método proceed(). Essa linha irá chamar o método que foi interceptado pelo interceptor. E com isso está encerrado o código dessa classe.
O código abaixo mostra como ficou a classe:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package br.com.mauda.seminario.cientificos.interceptor; import java.util.concurrent.TimeUnit; import javax.interceptor.AroundInvoke; import javax.interceptor.Interceptor; import javax.interceptor.InvocationContext; import org.apache.commons.lang3.time.StopWatch; import org.apache.logging.log4j.LogManager; @Interceptor @Cronometro public class CronometroInterceptor { @AroundInvoke public Object manage(InvocationContext ctx) throws Exception { StopWatch cronometro = StopWatch.createStarted(); try { return ctx.proceed(); } finally { if (cronometro.isStarted()) { cronometro.stop(); } LogManager.getLogger(ctx.getTarget().getClass()) .debug(ctx.getMethod() + ": executado em " + cronometro.getTime(TimeUnit.MILLISECONDS) + " ms"); } } } |
Passo 3 – Adicionar o interceptor no arquivo beans.xml
Esse passo irá adicionar o interceptor dentro do arquivo beans.xml.
Para adicionar é necessário utilizar a tag <interceptors> e dentro dessa tag colocar uma tag <class> com o package completo mais o nome da classe Interceptor e não a annotation.
Caso seja necessário adicionar mais interceptor, apenas adicione mais uma tag <class> dentro da tag <interceptors> da mesma forma que a primeira.
As linhas destacadas abaixo mostram essas modificações:
1 2 3 4 5 6 7 8 9 |
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="all"> <interceptors> <class>br.com.mauda.seminario.cientificos.interceptor.CronometroInterceptor</class> </interceptors> </beans> |
Passo 4 – Utilizar a annotation nos lugares desejados
Por fim agora é só utilizar a annotation criada nos métodos desejados para que estes sejam interceptados e cronometrados, como mostra os trechos de código abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//Importando a annotation @Cronometro import br.com.mauda.seminario.cientificos.interceptor.Cronometro; // Utilizando no método desejado @Cronometro public Musica findById(Long id) { try { Query byIdQuery = this.session.createQuery("FROM Musica as c WHERE c.id = :id"); byIdQuery.setParameter("id", id); return (Musica) byIdQuery.uniqueResult(); } catch (Exception e) { throw new Exception(e); } } |
O resultado esperado é parecido com o console abaixo:
1 2 |
23:39:34.967 [main] DEBUG br.com.mauda.seminario.cientificos.dao.MusicaDAO$Proxy$_$$_WeldSubclass - public br.com.mauda.seminario.cientificos.dao.MusicaDAO.findById(java.lang.Long): executado em 8 ms |
finnaly{
Duvidas ou sugestões? Deixe seu feedback! Isso ajuda a saber a sua opinião sobre os artigos e melhorá-los para o futuro! Isso é muito importante!
Até um próximo post!
Leave a Reply