# 2. Context

* #### @Configuration - Podemos configurar Datas de forma global, declarar Beans...

**Sempre que o Spring iniciar a aplicação, ele irá olhar para essa classe e levará em consideração as customizações e configurações que definirmos nessa classe de Configuração.**

***

* #### @ComponentScan - Podemos definir/excluir determinados pacotes que serão passados na anotação. Mostraremos para o Spring quais são os pacotes que ele irá fazer uma "varredura".

Ele irá buscar pelos Beans que ele irá gerenciar. **Serve só para algo customizado mesmo, pois o Spring em sí já faz uma varredura automática ao ser iniciado.**

```java
@Configuration
@ComponentScan(basePackages = "com.api.parkingcontrol")
public class BeanConfig{}
```

***

* #### @Bean - Ao invés de declararmos pro spring usando as anotações esteriótipos, faremos de outra maneira.

Criamos uma classe, por exemplo, chamada MyBean.

Dentro da BeanConfig, criaremos um método que irá retornar exatamente o Objeto que criamos.

```java
@Bean
public myBean myBean() {
    return new MyBean();
}
```

Pro Spring saber detectar que esse MyBean será um Bean gerenciado, precisamos passar @Bean.

Para podermos visualizar o que está dentro da Classe MyBean, faremos uma injeção de dependência dentro da Classe ParkingSpotController, assim como fizemos com o @Value.

Usa o Autowired para fazer a importação do MyBean, e pode chamar o metodo com myBean.method(). [Veja aqui](https://github.com/MichelliBrito/parking-control-api/blob/8df47619b3016659e88dedb591c2f90ba25b5f4e/src/main/java/com/api/parkingcontrol/controllers/ParkingSpotController.java#L73C1-L74C1)

Ok, isso foi um Bean criado por nós. Mas eventualmente usaremos Beans advindos de bibliotecas terceirizadas, como fazer nestes casos?

Dentro do nosso pom, inserimos uma dependência modelmapper, utilizada para conversões. [Veja aqui](https://github.com/MichelliBrito/parking-control-api/blob/8df47619b3016659e88dedb591c2f90ba25b5f4e/pom.xml#L38)

#### Declarando Bean de uma biblioteca externa

Declaremos o Bean ModelMapper dentro da classe que iremos utilizar, mostrando que mesmo que esse Bean não tenha sido criado por nós, o Spring irá também gerenciá-lo.

```java
(dentro da classe config)
@Bean
public ModelMapper modelMapper() {
    return new ModelPapper();
}
```

E dentro da controller, que é onde iremos iniciar, faremos a injeção. [Veja aqui](https://github.com/MichelliBrito/parking-control-api/blob/8df47619b3016659e88dedb591c2f90ba25b5f4e/src/main/java/com/api/parkingcontrol/services/impl/ParkingSpotServiceImpl.java#L29)

***

* #### @Lazy - Quando a gente não define nada na classe criada (passa somente @Component), o Spring internamente usa a "criação ansiosa". Já criando estes Beans, os deixando disponíveis para uso.

Mas podemos fazer um "start preguiçoso". **Ou seja, falar pro Spring criar esse Bean somente quando precisar**.

Passamos a anotação @Lazy e será feito dessa maneira.

E como acionar esse Bean em um momento específico pro Spring criar?

Bom, mesmo de sempre. Faremos a injeção de dependência no controller com @Autowired importanto o Bean e assim o Spring carregará o método com @Lazy. [Veja aqui](https://github.com/MichelliBrito/parking-control-api/blob/8df47619b3016659e88dedb591c2f90ba25b5f4e/src/main/java/com/api/parkingcontrol/controllers/ParkingSpotController.java#L46)

**Caso esse LazyBean não esteja importado dentro de algum método, não será inicializado pois o Spring não encontrará nenhum ponto de injeção de dependência.**

***

*   #### @Primary - Como é possivel ver no repositório desse projeto nos links acima. Nós temos uma interface chamada **ParkingSpotService**. Essa interface está sofrendo duas importações (ParkingSpotServiceImpl e ParkingSpotServiceImplV2).



Se você não especificar qual dessas o Spring irá considerar nos pontos de injeção que vamos criando, ele entrará em conflito. Precisamos declarar qual ele irá utilizar. Tipo quando passamos o arquivo no @Qualifier.

Então esse @Qualifier não irá existir. **Usaremos, portanto, o @Primary**. [Veja aqui](https://github.com/MichelliBrito/parking-control-api/blob/8df47619b3016659e88dedb591c2f90ba25b5f4e/src/main/java/com/api/parkingcontrol/services/impl/ParkingSpotServiceImpl.java#L18)

***

* #### @Scope - Utilizaremos o Controller novamente e, nela, passaremos o @Scope.

Utilizaremos o parâmetro singleton, conforme vimos na parte de [Beans](https://github.com/zenonxd/springboot-michelli?tab=readme-ov-file#beans). Em suma, o @Scope define como o Spring irá lidar com as criações dos Beans (dependendo do parâmetro).

***

* #### @PropertySource - E se quisermos criar outro arquivo .properties com configurações customizadas?

Cabe destacar que o Sring lê a application.properties por default.

Podemos criar no package Resources um "custom.properties". Contendo o que desejarmos. No controller, criaremos uma várivel do tipo de conteúdo que criamos no arquivo "properties". Se for uma String, criaremos uma variável tipo String usando Anottation @Value. [Veja aqui](https://github.com/MichelliBrito/parking-control-api/blob/8df47619b3016659e88dedb591c2f90ba25b5f4e/src/main/java/com/api/parkingcontrol/controllers/ParkingSpotController.java#L61)

Mas isso não é o suficiente. O Spring precisa saber o arquivo pro Spring. Passamos a anotação @PropertySource("classpath:custom.properties") [Veja aqui](https://github.com/MichelliBrito/parking-control-api/blob/8df47619b3016659e88dedb591c2f90ba25b5f4e/src/main/java/com/api/parkingcontrol/controllers/ParkingSpotController.java#L35)

* #### @PropertySources - Se for multiplos arquivos de .properties, usa ele para declarar todos os caminhos desejados.

***

*   #### @Profile - Imagine que temos um método que retorne a mesma coisa (objeto, por exemplo), porém com métodos diferentes e os dois estão com anotação @Bean.



Nessa situação, passaremos o @Profile dizendo qual será qual. Porém, essa forma não é a ideal, ao inciarmos a aplicação teremos um conflito. O Spring não consegue saber qual perfil está ativo.

**Jeitos de realizar**

1. Na nossa application.properties, colocaremos logo no começo: `spring.profiles.active=dev` ou =prod (o que tiver no @Profile).
2. Ao invés de usarmos a anotação dentro no método dentro da BeanConfig, criaremos uma classe para cada Profile. E assim sendo, declararemos o @Profile na classe em sí. [Veja aqui](https://github.com/MichelliBrito/parking-control-api/blob/8df47619b3016659e88dedb591c2f90ba25b5f4e/src/main/java/com/api/parkingcontrol/configs/DevBeanConfig.java#L9) Na .properties mantém o que a gente quer passar no profile.active. O que muda mesmo é onde declaramos o @Profile.
