---
# System prepended metadata

title: Spring notes

---

# Spring notes

DI can be done with those 3 types of configuration:
1. Full XML Config
2. XML Component Scan
3. Java Configuration Class

## 1) DI with applicationContext

### Setter injection 

**With a file.properties:**
```xml=
<context:property-placeholder location="classpath:toto.properties"/>

...

<bean id="idOfClass" class="pathToClass">
    <property name="propertyNameOfDependency" ref="idOfDependency"/>
    <property name="email" value="${toto.email}"/>
    ...
</bean>
```

NB: The properties need setter methods!
Cause Spring will look out for them in order to inject the properties.
:warning: How does Spring find those setters? --> by the name of the method! Thus the name **must** be `setFooProperty`

### Constructor injection

```xml=
<constructor-arg ref="idOfDependencyToInject"/>
```

### Scopes

```java=
context.getBean("<name_of_bean_in_context>", <interface>.class)
```
To modify a bean scope: just add a "scope" tag and singleton or prototype.
- `singleton`: default, only one instance of the object is created
- `prototype`: a new object is created for each request (the request being `context.getBean()`)


### Lifecyles

Custom code during bean initalization/destruction = **hooks** (you can hook in code)

To add hooks to a bean initalization/destruction: just add a "`init-method`" or "`destroy-method`" tag and a name of method.

```xml=
<bean id="myDanceCoach" class="com.luv2code.springdemo.DanceCoach" init-method="startup" destroy-method="destroy">
```

NB: prototype scope --> no destruction method!

___

## 2) DI with annotations

Annotate a bean instead of declaring it into `applicationContext.xml`:
```java=
@Component("thatSillyCoach")
```
```java=
@Component // Default id = name of the class with the first letter lower-cased (BigRectangle --> bigRectangle)
```

together with the following line into the `applicationContext.xml` (enables component scanning through a package)
```xml
<context:component-scan basepackage="com.luv2code.springdemo"/>
```

### Autowiring

Autowiring = injection
- Spring looks for a class/Bean (annotated with `@Component`) that matches the property (type of class or interface)
- Spring injects it automatically

#### Constructor injection

To inject into constructor, just add `@Autowired` above the construtor in which you want to inject.

NB: Starting with Spring 4.3, if a class, which is configured as a Spring bean, has only one constructor, the @Autowired annotation can be omitted and Spring will use that constructor and inject all necessary dependencies.

Regarding the default constructor: You either need the default constructor, a constructor with the @Autowired annotation when you have multiple constructors, or only one constructor in your class with or without the @Autowired annotation.

#### Setter injection

To inject into a property (setter injection), just add `@Autowired` above the setter of the given properties you want to inject.
NB: You do not have to call your setter method exactly `setFooProperty`. You're free to call it whatever you want.

#### Field injection

- Uses Java reflexion
- Fields are injected **right after construction of a bean**, before any config methods are invoked. Such a config field **does not have to be public**.

To do field injection, just add `@Autowired` above a property you want to inject.

NB: The reasons why field injection is frowned upon are as follows:
- You **cannot create immutable objects**, as you can with constructor injection (since it's injected after construction, it cannot be final, lazy at least ?)
- Your classes have **tight coupling with your DI container** and cannot be used outside of it
- Your classes **cannot be instantiated** (for example in unit tests) without reflection. You need the DI container to instantiate them, which makes your tests more like integration tests

#### Multiple implementations of a dependency (no unique bean)?

Together with the @Autowired annotation, add the following
```java=
@Qualifier("classNameOfComponent")
```

#### To inject properties for file.property

```java=
@Value("${foo.email}")
private String email;
    
@Value("${foo.team}")
private String team;
```

#### Scope

```java=
@Component
@Scope("prototype")
```

#### Hooks

```java=
@Component
public class Toto() {

    ... 
        
    @PostConstruct
    private void startup() {}
    
    @PreDestroy
    public void destroy() {}

}
```

## 3) DI with Java Configuration Class

Add a dedicated class:
```java=
@Configuration
@ComponentScan("com.luv2code.springdemo") // Optional if you declare the bean with @Bean
public class SportConfig {}
```

Replace the `ClassPathXmlApplicationContext` with
```java=
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SportConfig.class);
```

NB:  Spring Boot introduces the `@SpringBootApplication `annotation. This single annotation is equivalent to using `@Configuration`, `@EnableAutoConfiguration`, and `@ComponentScan`.

### Parallel Spring/Hilt


|               Spring               |                  Hilt                  |
|:----------------------------------:|:--------------------------------------:|
|               @Bean                |               @Provides                |
|             @Autowired             |                @Inject                 |
|        @Scope("singleton")         |               @Singleton               |
| @Qualifier("randomFortuneService") | @<Annotation given when bean declared\> |
    
    
Example: 

```java=
public class SportConfig {

  @Bean
  public Random random() {
    return new Random();
  }

    // Returns FortuneService
  @Bean
  public FortuneService randomFortuneService() {
    return new RandomFortuneService(random());
  }

    // Returns also FortuneService
  @Bean
  public FortuneService happyFortuneService() {
    return new HappyFortuneService();
  }

  @Bean
  public TennisCoach tennisCoach() {
    return new TennisCoach(randomFortuneService());
  }
}
```

```java=
  // Injection
  public TennisCoach(@Qualifier("randomFortuneService") FortuneService fortuneService) {
    this.fortuneService = fortuneService;
  }
```

```kotlin=
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

  @AuthInterceptorOkHttpClient
  @Provides
  fun provideAuthInterceptorOkHttpClient(
    authInterceptor: AuthInterceptor
  ): OkHttpClient {
      return OkHttpClient.Builder()
               .addInterceptor(authInterceptor)
               .build()
  }

  @OtherInterceptorOkHttpClient
  @Provides
  fun provideOtherInterceptorOkHttpClient(
    otherInterceptor: OtherInterceptor
  ): OkHttpClient {
      return OkHttpClient.Builder()
               .addInterceptor(otherInterceptor)
               .build()
  }
}
```

```kotlin=
class ExampleServiceImpl @Inject constructor(
  @AuthInterceptorOkHttpClient private val okHttpClient: OkHttpClient
) : ...
```

### Use property file

`@PropertySource("classpath:file.properties")` into the class configuration.

## MVC

`/WEB-INF/view/show-student-list.jsp`
prefix/../suffix

JSP = JavaServer Pages: enables you to write dynamic, data-driven pages for your Java web applications

### Bind a form

```java=
@GetMapping("/greeting")
public String greeting(
  @RequestParam(name = "name", required = false, defaultValue = "World") String name, Model model) {
model.addAttribute("message", name.toUpperCase());
return "greeting";
  }
```

```htmlmixed=
<p th:text="'Hello ' + ${param.name} + '!'"></p>
```

```htmlmixed=
<p th:text="'Hello ' + ${message} + '!'"></p>
```


spring web flux
web flux ! notion reactive