A diferença entre CDI e EJB Singleton
1. Visão geral
Neste tutorial, daremos uma olhada mais de perto em dois tipos desingletons disponíveis no Java EE. Vamos explicar e demonstrar as diferenças e ver os usos adequados para cada um.
Primeiro, vamos ver o que são os singletons antes de entrar em detalhes.
2. Padrão de Design Singleton
Lembre-se de que uma maneira comum de implementarSingleton Pattern é com uma instância estática e um construtor privado:
public final class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
Mas, infelizmente, isso não é realmente orientado a objetos. E tem algunsmulti-threading issues.
No entanto, os containers CDI e EJB nos fornecem uma alternativa orientada a objetos.
3. CDI Singleton
ComCDI (Contexts and Dependency Injection), podemos criar singletons facilmente usando a anotação@Singleton. Esta anotação faz parte do pacotejavax.inject. Ele instrui o contêiner parainstantiate the singleton oncee passa sua referência para outros objetos durante a injeção.
Como podemos ver, a implementação de singleton com CDI é muito simples:
@Singleton
public class CarServiceSingleton {
// ...
}
Nossa turma simula uma oficina de automóveis. Temos várias instâncias de váriosCars, mas todas usam a mesma loja para manutenção. Portanto, Singleton é um bom ajuste.
Podemos verificar se é a mesma instância com um teste JUnit simples que solicita o contexto para a classe duas vezes. Observe que temos um método auxiliargetBean aqui para facilitar a leitura:
@Test
public void givenASingleton_whenGetBeanIsCalledTwice_thenTheSameInstanceIsReturned() {
CarServiceSingleton one = getBean(CarServiceSingleton.class);
CarServiceSingleton two = getBean(CarServiceSingleton.class);
assertTrue(one == two);
}
Because of the @Singleton annotation, the container will return the same reference both times. Se tentarmos isso com um bean gerenciado simples, entretanto, o contêiner fornecerá uma instância diferente a cada vez.
E embora isso funcione da mesma forma parajavax.inject.Singleton oujavax.ejb.Singleton, there’s a key difference between these two.
4. EJB Singleton
Para criar um singleton EJB, usamos a anotação@Singleton do pacotejavax.ejb. Desta forma, criamos umSingleton Session Bean.
Podemos testar essa implementação da mesma maneira que testamos a implementação do CDI no exemplo anterior, e o resultado será o mesmo. Singletons EJB, como esperado, fornecem a instância única da classe.
No entanto,EJB Singletons also provide additional functionality in the form of container-managed concurrency control.
Quando usamos esse tipo de implementação, o contêiner EJB garante que todos os métodos públicos da classe sejam acessados por um único encadeamento por vez. Se vários threads tentarem acessar o mesmo método, apenas um thread poderá usá-lo enquanto outros aguardam sua vez.
Podemos verificar esse comportamento com um teste simples. Apresentaremos uma simulação de fila de serviço para nossas classes singleton:
private static int serviceQueue;
public int service(Car car) {
serviceQueue++;
Thread.sleep(100);
car.setServiced(true);
serviceQueue--;
return serviceQueue;
}
serviceQueue é implementado como um inteiro estático simples que aumenta quando um carro “entra” no serviço e diminui quando ele “sai”. Se o contêiner fornecer um bloqueio adequado, essa variável deverá ser igual a zero antes e depois do serviço e igual a uma durante o serviço.
Podemos verificar esse comportamento com um teste simples:
@Test
public void whenEjb_thenLockingIsProvided() {
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
int serviceQueue = carServiceEjbSingleton.service(new Car("Speedster xyz"));
assertEquals(0, serviceQueue);
}
}).start();
}
return;
}
Este teste inicia 10 threads paralelos. Cada thread instancia um carro e tenta repará-lo. Após o atendimento, afirma que o valor deserviceQueue voltou a zero.
Se, por exemplo, executarmos um teste semelhante no CDI singleton, nosso teste falhará.
5. Conclusão
Neste artigo, passamos por dois tipos de implementações singleton disponíveis no Java EE. Vimos suas vantagens e desvantagens e também demonstramos como e quando usar cada um.
E, como sempre, o código-fonte completo está disponívelover on GitHub.