Service Locator Pattern Java Spring Boot
O service locator pattern é um pattern suportado pela injeção de dependência Spring. Service Locator Java Spring nem vai doer, eu prometo!
Nesse artigo irei demonstrar como utilizei ele para resolver um problema. Sendo assim, vamos ao problema.
O Problema
Vamos imaginar uma aplicação Java em que você vai precisar utilizar 3 provedores (repositórios) de arquivos diferentes, que podem ser:
- Azure blobs
- Amazon S3
- File System do próprio servidor
Porém, minha aplicação pode ser utilizada em diversos clientes, sendo assim, cada um dos clientes pode escolher qual repositório utilizar.
Mãos ao código! (A mão da gambirra chega a tremer, sqn!)
1 – O contrato
Vamos definir um contrato (nossa interface) para o problema acima.
Concordamos que indiferente do tipo de repositório que vamos utilizar vamos precisar das seguintes operações para os arquivos:
- Salvar
- Baixar (Recuperar o arquivo)
- Deletar
Vamos considerar essas operações minimas que teremos nos nossos provedores.
Então agora vamos definir nossa interface:
public interface IArmazenamentoService {
void salvar(String caminhoArquivo, byte[] arquivo);
byte[] baixar(String caminhoArquivo);
void deletar(String caminhoArquivo);
}
Agora vamos implementar nossos serviços que irão implementar essa interface.
@Component("ArmazenamentoLocalService") public class ArmazenamentoLocalService implements IArmazenamentoService { //Implementa os metodos conforme a regra do serviço de armazenamento }
@Component("ArmazenamentoAmazonService") public class ArmazenamentoAmazonService implements IArmazenamentoService { //Implementa os metodos conforme a regra do serviço de armazenamento }
@Component("ArmazenamentoAzureService") public class ArmazenamentoAzureService implements IArmazenamentoService { //Implementa os metodos conforme a regra do serviço de armazenamento }
Contrato criado e assinado por seus respectivos serviços.
Agora precisamos configurar o Spring para criar uma instancia do nosso serviço de armazenamento.
Porém vamos fazer isso sem os famosos if’s. Vamos fazer através do pattern utilizando uma pré-configuração.
2 – Configurando o Service Locator
Primeiro vamos definir um contrato para a fabrica de serviço de armazenamento.
public interface IArmazenamentoFactory { IArmazenamentoService get(String type); }
Na interface criada acima é possível visualizar que foi definido que quem implementar a interface “IArmazenamentoService” precisará ter um método que recebe o tipo de armazenamento, que será, “Local, Azure ou Amazon”, e irá retornar uma instancia do serviço informado.
Criando nosso Configuration do spring.
@Configuration public class ArmazenamentoConfiguration { @Bean("iArmazenamentoFactory") public FactoryBean serviceLocatorFactoryBean() { ServiceLocatorFactoryBean factoryBean = new ServiceLocatorFactoryBean(); factoryBean.setServiceLocatorInterface(IArmazenamentoFactory.class); return factoryBean; } }
Pronto! Agora só precisamos implementar um service que vai utilizar toda essa nossa parafernália.
3 – Utilizando serviços implementados
Vamos considerar que teremos um serviço que utilizará a nossa fabrica para criar o service a partir da configuração que pode vir de qualquer lugar.
@Service public class ArmazenamentoBusiness { private IArmazenamentoService armazenamentoService; private String servicoArmazenamento = "ArmazenamentoLocalService" @Autowired public ArmazenamentoBusiness(IArmazenamentoFactory armazenamentoFactory) { this.armazenamentoService= armazenamentoFactory.get(this.servicoArmazenamento); } public void salvar(String caminhoArquivo, byte[] arquivo) { this.armazenamentoService.salvar(String caminhoArquivo, byte[] arquivo); } public void deletar(String caminhoArquivo) { this.armazenamentoService.deletar(String caminhoArquivo); } public byte[] baixar(String caminhoArquivo){ this.armazenamentoService.baixar(String caminhoArquivo); } }
Viu! Foi tranquilo implementar o Service Locator Java Spring.
Utilizei aqui a biblioteca Lombok. Caso queiram conhecer mais sobre, temos um arquivo que fala sobre ela: https://coffops.com/utilizando-lombok-com-java-nointellij/
Caso queiram realizar o download do código acima, deixo aqui com vocês o link do github.
https://github.com/aluizrech/ServiceLocatorCoffops
Caso que alguém tenha interesse que terminamos as implementações de integração para cada tipo de serviço de armazenamento, basta deixar nos comentários.
Abraços!