0Pricing
Java Academy · Aula

Proxies Dinâmicos com InvocationHandler

Crie proxies dinâmicos do JDK para interceptar chamadas de métodos de interfaces destinadas a registro, armazenamento em cache e novas tentativas.

Proxies Dinâmicos com InvocationHandler é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.

O Que É um Proxy Dinâmico?

Um proxy dinâmico do JDK é um objeto criado em tempo de execução que implementa uma ou mais interfaces. Todas as chamadas de métodos são encaminhadas para um InvocationHandler fornecido por você.

Criando um Proxy com Proxy.newProxyInstance

Chame Proxy.newProxyInstance(classLoader, interfaces[], handler) para criar um proxy. O proxy implementa todas as interfaces listadas.

UserService proxy = (UserService) Proxy.newProxyInstance(
    UserService.class.getClassLoader(),
    new Class[]{UserService.class},
    new LoggingHandler(realService)
);
proxy.findById(42L); // intercepted by LoggingHandler

A Interface InvocationHandler

Implemente InvocationHandler para tratar cada chamada de método. O manipulador recebe o objeto proxy, o método invocado e os argumentos.

public class LoggingHandler implements InvocationHandler {
    private final Object target;
    public LoggingHandler(Object target) { this.target = target; }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(">> " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("<< " + method.getName());
        return result;
    }
}

Proxy para Cache

Um InvocationHandler pode armazenar resultados em cache: se o cache contiver um resultado para os argumentos, retorne-o; caso contrário, chame o método real e armazene o resultado.

public class CachingHandler implements InvocationHandler {
    private final Object target;
    private final Map<String, Object> cache = new HashMap<>();
    public CachingHandler(Object target) { this.target = target; }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String key = method.getName() + Arrays.toString(args);
        return cache.computeIfAbsent(key, k -> {
            try { return method.invoke(target, args); }
            catch (Exception e) { throw new RuntimeException(e); }
        });
    }
}

Proxy para Lógica de Novas Tentativas

Envolva as chamadas de métodos em um laço de novas tentativas. Se ocorrer uma exceção, tente novamente até N vezes antes de relançá-la.

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    for (int attempt = 1; attempt <= 3; attempt++) {
        try { return method.invoke(target, args); }
        catch (InvocationTargetException e) {
            if (attempt == 3) throw e.getCause();
            Thread.sleep(1000L * attempt);
        }
    }
    throw new RuntimeException("unreachable");
}

Proxy para Gerenciamento de Transações

O @Transactional do Spring usa um proxy dinâmico para iniciar uma transação antes de uma chamada de método e confirmá-la ou revertê-la depois — tudo sem que o chamador perceba.

Verificando se um Objeto É um Proxy

Use Proxy.isProxyClass(obj.getClass()) para detectar proxies e Proxy.getInvocationHandler(proxy) para obter o manipulador.

if (Proxy.isProxyClass(service.getClass())) {
    InvocationHandler h = Proxy.getInvocationHandler(service);
    System.out.println("Handler: " + h.getClass().getSimpleName());
}

Limitações dos Proxies Dinâmicos do JDK

Os proxies dinâmicos do JDK funcionam apenas com interfaces — eles não podem criar proxies de classes concretas. Para criar proxies baseados em classes, use CGLIB (que o Spring também usa internamente para classes @Configuration).

CGLIB como Alternativa

CGLIB gera uma subclasse da classe-alvo em tempo de execução, substituindo todos os métodos que não são finais. O Spring usa CGLIB quando não há interfaces presentes. Nenhuma anotação é necessária — o funcionamento é transparente.

Proxy no Hibernate

O Hibernate carrega associações de entidades de forma tardia usando proxies CGLIB/Byte Buddy. Quando você acessa uma coleção de carregamento tardio, o proxy dispara uma consulta SQL.

// Hibernate creates a proxy for:
@ManyToOne(fetch = FetchType.LAZY)
private Department department;
// Accessing dept triggers a DB query via the proxy

Desempenho dos Proxies

O despacho de métodos por um proxy dinâmico é aproximadamente 5 a 10 vezes mais lento que uma chamada direta. Para caminhos muito críticos, considere a geração de código em tempo de compilação (APT) ou MethodHandles em vez de proxies dinâmicos.

Verificação Rápida

Qual é a principal limitação dos proxies dinâmicos do JDK?

Recapitulação

Os proxies dinâmicos do JDK interceptam chamadas de métodos de interfaces por meio de InvocationHandler. Use-os para registro, cache, novas tentativas e gerenciamento de transações. Para criar proxies de classes, use CGLIB. Armazene a criação de proxies em cache — ela usa reflexão e não é gratuita.

Perguntas Frequentes

A aula “Proxies Dinâmicos com InvocationHandler” é grátis?

Sim — o texto completo de “Proxies Dinâmicos com InvocationHandler” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.

O que vou aprender em “Proxies Dinâmicos com InvocationHandler”?

Crie proxies dinâmicos do JDK para interceptar chamadas de métodos de interfaces destinadas a registro, armazenamento em cache e novas tentativas. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Java Academy?

Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Proxies Dinâmicos com InvocationHandler”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Java Academy?

Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Inspeção de Classes com Reflexão
  2. Invocação de Métodos e Acesso a Campos
  3. Proxies Dinâmicos com InvocationHandler
  4. Desempenho da Reflexão e Alternativas
← Voltar para Java Academy