Spring Framework: o que é, seus módulos e exemplos!
Spring é um framework Java desenvolvido para facilitar o desenvolvimento de aplicações explorando os conceitos de Inversão de Controle e Injeção de Dependência. Desta forma, ao adotá-la, temos uma tecnologia que não só nos fornece os recursos que a maioria das aplicações precisa, como módulos para persistência de dados, integração, segurança, testes, desenvolvimento web, mas também Fornecer um conceito a seguir nos permite para criar soluções menos acopladas, mais coesas e, portanto, mais fáceis de entender e manter.
Por que o Spring foi criado?
O Spring foi criado devido às dificuldades que os programadores tiveram em criar um determinado tipo de aplicação, mais precisamente, uma aplicação corporativa. Na época, a plataforma Java dedicada a isso (chamada J2EE) era jovem e tinha boas ideias para construir aplicações distribuídas leves, com um amplo leque de opções/ferramentas, mas com algumas limitações. Essas limitações fazem com que a programação dependa de muitas interfaces e muitas configurações. No final, muitas vezes há uma solução tediosa que traz mais do que é realmente necessário.
Além disso, precisamos usar um servidor de aplicativos pesado, o que torna a programação e a depuração do aplicativo mais lentas.
Inversão de Controle
Inversão de Controle (ou IoC, em inglês) é a interrupção do fluxo de execução do código, retirando o controle dele de alguma forma e delegando-o a uma dependência ou container. O objetivo principal é reduzir o acoplamento de código.
Em Java, até falamos sobre classes desacopladas. Além de facilitar a alteração ou adição do comportamento do sistema quando necessário, isso pode melhorar muito a capacidade de manutenção. Também reduz a possibilidade de erros em cascata.
No Spring Framework, as instâncias de classe são fracamente acopladas, ou seja, os objetos têm interdependências mínimas.
A inversão de controle no Spring é facilitada por outro padrão de projeto: injeção de dependência.
Injeção de Dependência
A injeção de dependência foi projetada para evitar o acoplamento de código em um aplicativo. Em outras palavras, o que o objeto precisa é da proveniência da instância da classe sem instanciar a si mesma. Podemos dizer que a Injeção de Dependência é uma forma de aplicar a Inversão de Controle.
No Spring Framework, podemos realizar a injeção de dependência da seguinte forma:
anotação @Autowired; utilizando o construtor da classe (Constructor Injection); utilizando o método setter (Setter Injection).
A anotação @Autowired define o ponto em que a injeção de dependência será executada. Por exemplo, no código abaixo:
@Service public class ExampleService { @Autowired private ExampleRepository exampleRespository; // construtor, getters e setters }
As instâncias da classe ExampleRepository são definidas como dependências que serão injetadas pelo container spring. Toda vez que ExampleService é instanciado, o Spring gerencia todo o ciclo de vida dessa dependência.
Usar @Autowired no exemplo acima é conhecido como injeção de campo e, embora seja o mais comumente usado, não é a melhor opção para realizar a injeção.
O código de injeção do construtor recomendado pela equipe do spring é o seguinte:
@Service
public class ExampleService { private ExampleRepository exampleRepository; public ExampleService(ExampleRepository exampleRepository) { this.exampleRepository = exampleRepository; } }
As vantagens desse padrão de injeção são maior legibilidade do código, facilidade de manutenção e facilidade de construção de testes (que também são suportados pelo Spring Framework).
Injeção via método setter:
@Service public class ExampleService { private ExampleRepository exampleRepository; @Autowired
public void setExampleRepository(ExampleRepository exampleRepository) { this.exampleRepository = exampleRepository } }
Agora que abordamos esses aspectos importantes do Spring Framework, vamos falar sobre alguns de seus principais módulos e algumas das anotações usadas. Por fim, mostrarei um pequeno tutorial de java spring com algumas anotações para esses módulos.
Nota 1: Provavelmente algumas das anotações são de outro módulo, mas isso não mudará.
Nota 2: As anotações a seguir são as anotações principais de cada módulo, mas não se limitam a isso.
Nota 3: Algumas anotações requerem ou suportam parâmetros, embora não tratemos desse aspecto. No exemplo, estaremos trabalhando em um aplicativo Spring RESTful, que ficará visível.
Spring Boot no Spring Framework
O Spring Boot facilita muito a criação de aplicativos Java que usam o ecossistema Spring e executam projetos com pouca ou nenhuma configuração. Ele abstrai toda a complexidade que uma configuração completa pode trazer (“apenas execute”).
Este módulo Spring Framework é construído sobre a ideia de convenção sobre configuração. Ou seja, basta usar os submódulos necessários e não se preocupar com o trabalho de configuração da mola.
Algumas anotações utilizadas:
@Configuration – define uma classe como a origem das definições de bean, é uma das anotações essenciais se você usar a configuração baseada em Java.
@Bean – Usado em um método de uma classe, geralmente marcado com @Configuration, para indicar que o Spring Framework deve chamar o método e gerenciar o objeto que ele retorna, ou seja, o objeto agora pode ser injetado em qualquer lugar da aplicação (lembra da Dependency Injection? ) .
@Autowired – Conforme discutido e exemplificado, definindo pontos de injeção de dependência em classes.
@Scope – Define o ciclo de vida dos objetos gerenciados pelo Spring Framework. Podemos combiná-lo com outras anotações como @Component ou @Bean.
@Primary – usado quando temos dois métodos anotados com @Bean retornando o mesmo tipo de objeto. Quando solicitado, o Spring precisa saber qual injetar por padrão. Indica qual deve ser o valor padrão.
Observação: para alterar o padrão, use a anotação @Qualifier.
@SpringBootApplication – Combina @Configuration, @EnableAutoConfiguration e @ComponentScan. Dessa forma, não precisamos instalar um servidor web porque o Spring Boot vem com um servidor Tomcat integrado.
Essa anotação permite a configuração baseada em Java e os recursos de verificação e configuração automática de componentes do Spring Boot.
@Profile – Define em qual perfil tal bean deve ser carregado. Comum quando certas classes devem ser carregadas apenas em ambientes de desenvolvimento, produção ou teste.
@EnableAutoConfiguration – habilita o recurso de configuração automática.
@EnableAsync – quando você precisa fazer algo com o sistema em segundo plano (outro thread). Essa anotação deve ser colocada em classes anotadas com @Configuration para que o Spring habilite o suporte à execução assíncrona.
@Async – Use @EnableAsync para habilitar a execução do método assíncrono, marcando qualquer método de um bean gerenciado. Uma vez que tal método é chamado, o Spring garantirá que ele será executado em outro thread.
@Component – Indica que uma classe será gerenciada pelo contêiner Spring (Spring Container IoC).
@ComponentScan – Usado em uma classe de configuração para indicar quais pacotes ou classes o Spring deve verificar para que essa configuração funcione.
@Service – define uma classe de serviço.
@RestControllerAdvice – Uma combinação de anotações @ControllerAdvice e @ResponseBody. Ele informa ao Spring que é um componente especializado em manipulação de exceções e que o retorno de seus métodos deve ser inserido no corpo da resposta HTTP e convertido em JSON.
@ControllerAdvice – Manipulando exceções em aplicativos Spring MVC. É usado para tratamento global de erros. Você tem controle total sobre o corpo da resposta e o código de status.
Spring Data JPA
O Spring Data visa fornecer um modelo de programação baseado em Spring para acesso fácil e sem esforço aos dados, preservando as características especiais do armazenamento de dados subjacente.
Facilita o uso de tecnologias de acesso a dados, bancos de dados relacionais e não relacionais, recursos de mapeamento de abstrações e objetos personalizáveis e consultas dinâmicas.
Algumas anotações usadas:
@Transactional – Configura o comportamento transacional do método.
@NoRepositoryBean – Portanto, o Spring Framework não criará beans de interface de repositório comuns para sub-repositórios.
@Repository – define um repositório de bean (este não é Spring Data, mas tem uma boa conexão com ele)
@Query – Usado para fornecer implementações JPQL para métodos de repositório.
@Param – Define os parâmetros nomeados que serão passados para a consulta.
@Id – Define que a propriedade é um identificador.
@Transient – Marca um campo da classe de modelo como transiente. Portanto, o mecanismo de armazenamento de dados não lê nem grava o valor desse campo.
@GeneratedValue – Define que a geração do ID da entidade será gerenciada pelo provedor de persistência (JPA).
Spring Security no Spring Framework
O Spring Security é uma estrutura de autenticação e autorização poderosa e altamente personalizável para proteger aplicativos baseados em Spring Framework.
Ele se concentra em fornecer autenticação e autorização para aplicativos Java. Para isso, fornece ferramentas de extensão e atende a todas as customizações de segurança exigidas por um projeto Java Spring.
Algumas anotações utilizadas:
@EnableWebSecurity – habilita recursos de segurança.
@EnableAuthorizationServer – habilita AuthorizationServer.
@EnableResourceServer – Permite que o aplicativo se comporte como um servidor de recursos.
@EnableGlobalMethodSecurity – habilita a segurança do método global.
@Secured – Usado para especificar uma lista de funções (funções) em um método.
@PreAuthorize – Fornece controle de acesso baseado em expressão.
@PreFilter – Filtra parâmetros de coleção antes de executar métodos, usando Spring EL para definir regras de segurança refinadas. A filtragem é aplicada à lista passada como parâmetro de entrada para o método anotado.
@PosFilter – Filtra a lista de objetos de acordo com uma regra de segurança personalizada que definimos, ou seja, define a lista de retorno de métodos que filtram aplicando essa regra a todos os elementos da lista.
Se a avaliação for verdadeira, o item permanecerá na lista, caso contrário o item será removido.
@AuthenticationPrincipal – diz ao Spring para injetar o usuário logado no aplicativo.
Spring Web e Spring MVC
Spring Web é usado para construir aplicações web, incluindo RESTful, usando Spring MVC. Essencial para criar aplicativos da Web baseados no Spring Framework.
Spring MVC é um módulo Spring que ajuda a criar aplicações web de forma simples, simples e elegante que possibilita a construção de aplicações web robustas e flexíveis, como o próprio nome sugere, é baseado no padrão MVC.
No Spring MVC, os controladores são criados com a anotação @Controller ou @RestController e, para cada método, são mapeados para a URL onde o controlador será invocado.
Algumas anotações utilizadas:
@RequestMapping – Mapeamento de solicitações REST.
@Controller – define uma classe que contém os métodos do framework Spring MVC.
@RestController – define uma classe que contém métodos de API RESTful.
@RequestBody – mapeia o corpo da solicitação HTTP para um objeto.
@PathVariable – Define os parâmetros recebidos da solicitação.
@RequestParam – Usando esta anotação, podemos acessar parâmetros de solicitações HTTP.
@ExceptionHandler – lida com exceções. A configuração do Spring detecta essa anotação e registra o método como um manipulador de exceção para a classe de exceção do parâmetro e sua interface.
@ResponseStatus – Usando esta anotação, podemos especificar o status HTTP desejado da resposta.
@ModelAttribute – Define o modelAttribute que será usado no formulário HTML. Podemos acessar elementos que já existem no modelo MVC @Controller, apoiando as chaves do modelo.
@CrossOrigin – Habilita a comunicação entre origens para métodos de manipulador de solicitação.
@SessionAttributes – Declare atributos de sessão, listando nomes de atributos de modelo que devem ser armazenados de forma transparente na sessão como um bean de suporte de formulário entre solicitações subsequentes.
JPA (Java Persistence API)
Algumas notas importantes para uso em aplicativos Java Spring Framework (esta é uma seção de bônus, divirta-se!)
@Entity – especifica que a classe representa uma entidade no banco de dados. O estado das classes anotadas com essa anotação é gerenciado pelo contexto de persistência subjacente.
@Basic – Mapeia tipos básicos de propriedades para colunas de tabelas no banco de dados.
@Cacheable – Especifica se a entidade deve ser armazenada no cache de segundo nível.
@Table – especifica a tabela de entidade anotada.
@Column – especifica o mapeamento entre as propriedades de base e as colunas da tabela de banco de dados.
@Id – Especifica o identificador da entidade. Qualquer entidade deve ter uma propriedade identificadora que é usada ao carregar a entidade no contexto de persistência fornecido.
@GeneratedValue – Especifica que os valores do identificador de entidade são gerados automaticamente usando uma coluna de identidade, string de banco de dados ou gerador de tabela.
Hibernate (uma implementação de JPA) suporta mapeamento @GeneratedValue, mesmo para identificadores UUID.
@Transient – Especifica que uma determinada propriedade de entidade não deve ser persistida. Praticamente a mesma ideia das anotações do Spring Data.
@Lob – especifica que a propriedade da anotação atual representa um tipo de objeto grande.
@OneToOne – especifica um relacionamento de banco de dados um para um.
@ManyToOne – especifica um relacionamento de banco de dados muitos para um.
@OneToMany – especifica um relacionamento de banco de dados um para muitos.
@ManyToMany – especifica um relacionamento de banco de dados muitos para muitos.
@JoinColumn – especifica a coluna FOREIGN KEY a ser usada ao ingressar em associações de entidades ou coleções incorporáveis.
@JoinTable – Especifica uma tabela vinculada entre duas outras tabelas de banco de dados.
@MapsId – Especifica que o identificador de identidade é mapeado pelo @ManyToOne da anotação atual ou @OneToOne associado.
@ElementCollection – especifica uma coleção de tipos primitivos ou incorporáveis.
@Embeddable – especifica um tipo incorporável. Assim como os tipos primitivos, os tipos incorporáveis não têm identidade e são gerenciados pela entidade que possuem.
@Embedded – especifica que a propriedade de entidade fornecida representa um tipo incorporável.
@Enumerated – especifica que a propriedade de entidade representa um tipo enumerado.
@JoinColumns – Usado para agrupar várias anotações @JoinColumn usadas ao mapear associações de entidades ou coleções incorporáveis usando identificadores compostos.
@NamedQuery – especifica uma consulta JPQL que pode ser recuperada posteriormente por seu nome.
@OrderBy – especifica a propriedade de entidade a ser usada para ordenação ao obter a coleção anotada atual.
@PersistenceContext – especifica o EntityManager que precisa ser injetado como uma dependência.
@Temporal – Especifica o tipo de hora de uma propriedade de entidade java.util.Date ou java.util.Calendar.
@Access – especifica o tipo de acesso da classe de entidade associada, superclasse associada ou entidade incorporável e propriedades de classe.
@Inheritance – especifica a estratégia de herança para uma determinada hierarquia de classe de entidade.
@ForeignKey – especifica a chave estrangeira associada ao mapeamento @JoinColumn.
@Mapkey – Especifica a chave associada ao java.util.Map cujo tipo de chave é a chave primária ou propriedade da entidade que representa o valor mapeado.
@NamedQueries – Usado para agrupar várias anotações @NamedQuery.
@PersistenceUnit – Especifica o EntityManagerFactory que precisa ser injetado como uma dependência.
@PersistenceUnits – Usado para agrupar várias anotações @PersistenceUnit.
@PostLoad – Especifica o método de retorno de chamada a ser acionado depois que a entidade for carregada.
@PostPersist – Especifica um método de retorno de chamada que é acionado depois que a entidade é persistida.
@PostRemove – Especifica o método de retorno de chamada a ser acionado após a remoção da entidade.
@PostUpdate – Especifica o método de retorno de chamada a ser acionado após a atualização da entidade.
@PrePersist – Especifica o método de retorno de chamada a ser acionado antes que a entidade seja persistida.
@PreRemove – especifica um método de retorno de chamada a ser acionado antes que a entidade seja removida.
@PreUpdate – especifica um método de retorno de chamada a ser acionado antes que a entidade seja atualizada.
Conclusão
Como você pode ver, existem muitas ferramentas que facilitam o trabalho com Java. Aproveite a lista de notas e aumente sua produtividade!
Mais uma coisa a salientar: “O Spring Framework é uma obrigação”. Para uso em aplicações web e no próprio Java, os frameworks e seus módulos são essenciais para agilizar seu trabalho.