# Spring

## Inversion Of Control (IOC)

* If class A depend on class B , pass the declaration of class B to third party to declare
* Example: If a graduate want to find a suitable job , he should find the agent to help him to look for his suitable job according to his abilities, instead of every student find for the same job.&#x20;
* Dependency injection is a one of the example of inversion of control
* Without IOC&#x20;

```java
public class Graduate {
    private Programmer programmer;
}
// That assume all the graduate must find a programmer job, which is strongly coupled
```

* With IOC

```java
public class Graduate{
    private Job job;
    public void setJob(Job job){
        this.job = job;
    }
}

// The job class is an interface;
// The job of the graduate will handled by another class(e.g Main class)
// which make the graduate loosely coupled with Job class
```

## Dependency Injection

### Initial&#x20;

```java
public class Lesson{
    private Student student;
    public Lesson(){
        this.student = new Student();
    }
}
```

### Dependency Injection (by constructor)

```java
public class Lesson{
    private Student student;
    public Lesson(Student exampleStudent){
        this.student = exampleStudent;
    }
}
```

### Dependency Injection (by setter)

```java
public class Lesson{
    private Student student;
    public void setStudent(student exampleStudent){
        this.student = new Student();
    }
}
```

* Initially,  lesson class is fixed with a specific student class. If we declare new Lesson class,  the student must be the same as every lesson class, which will cause out coupling.&#x20;
* By using dependency injection, lesson class and student will be independent to each other.

## Why Spring?&#x20;

* It has strong IOC container (Application Context) which manage and create the beans
* Developer can do dependency injection easily by using the bean of container&#x20;

## Structure of Java Spring&#x20;

![](https://1374779285-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MFW3x2aqEO8GF2kr3VU%2F-MIJ5CqrA1F_ZCCAG86-%2F-MIJ5xHXDcJMrWTIJ0qQ%2FCapture.PNG?alt=media\&token=2a5ecec2-d035-418f-ba32-cca2d6f19903)

### Data Access Integration

* Provide several popular API , such as hibernate, JPA
* Make the syntax of connecting database simpler

### Web

* Provide several web function, such as file reader
* Define Controller, Model and View

### Core&#x20;

* Application Context Container or Bean Factory Container is a container to contain the bean factory which is a xml file traditionally
* &#x20;Application Context Container&#x20;

```java
package com.yiibai;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class MainApp {
   public static void main(String[] args) {
      XmlBeanFactory factory = new XmlBeanFactory
                             (new ClassPathResource("Beans.xml"));

      HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");
      obj.getMessage();
   }
}
```

* Bean Factory Container

```java
package com.yiibai;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class MainApp {
   public static void main(String[] args) {
      XmlBeanFactory factory = new XmlBeanFactory
                             (new ClassPathResource("Beans.xml"));

      HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");
      obj.getMessage();
   }
}
```

## Bean

### &#x20; Introduction

* Bean can be instantiated as a instance of the class, which is similar with the below syntax to declare the new instance - sample Student

```java
Student sampleStudent = new Student("Chan Tai Man", 12);
```

* Bean can rely on another beans by using auto wire
* Example of creating bean by using traditional xml

```java
// HelloWorld.java
package com.yiibai;

public class HelloWorld {
   private String message;

   public void setMessage(String message){
      this.message  = message;
   }

   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
}
```



```java
// MainApp.java
package com.yiibai;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = 
             new ClassPathXmlApplicationContext("Beans.xml");

      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");

      obj.getMessage();
   }
}
```

```markup
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="helloWorld" class="com.yiibai.HelloWorld">
       <property name="message" value="Hello World!"/>
   </bean>

</beans>
```



```java
// Your Message : Hello World!
```

### Scope

#### Type

* There are 5 types of scope - singleton, prototype, request, session and global session
* **Singleton**: This scopes the bean definition to a single instance per Spring IoC container    (default)
* **Prototype**: This scopes a single bean definition to have any number of object instances.
* Request: This scopes a bean definition to an HTTP request. Only valid in the context of a web-aware Spring Application Context.
* Session: This scopes a bean definition to an HTTP session. Only valid in the context of a web-aware Spring Application Context.
* Global-session: This scopes a bean definition to a global HTTP session. Only valid in the context of a web-aware Spring Application Context.

#### Singleton vs Prototype

```java
// Main.java
package com.yiibai;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = 
             new ClassPathXmlApplicationContext("Beans.xml");

      HelloWorld objA = (HelloWorld) context.getBean("helloWorld");

      objA.setMessage("I'm object A");
      objA.getMessage();

      HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
      objB.getMessage();
   }
}
```

* Singleton

```markup
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="helloWorld" class="com.yiibai.HelloWorld" 
      scope="singleton">
   </bean>

</beans>
```

Output

```
Your Message : I'm object A
Your Message : I'm object A
```

* Prototype

```markup
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="helloWorld" class="com.yiibai.HelloWorld" 
      scope="prototype">
   </bean>

</beans>
```

Output&#x20;

```markup
Your Message : I'm object A
Your Message : null
```

### Life Cycle

* Initialize and Destroy
* we can add custom event for each as a listener

```java
// HelloWorld.java
package com.yiibai;

public class HelloWorld {
   private String message;

   public void setMessage(String message){
      this.message  = message;
   }
   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
   public void init(){
      System.out.println("Bean is going through init.");
   }
   public void destroy(){
      System.out.println("Bean will destroy now.");
   }
}
```

```java
// Main.java
package com.yiibai;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
   public static void main(String[] args) {

      AbstractApplicationContext context = 
                          new ClassPathXmlApplicationContext("Beans.xml");

      HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
      obj.getMessage();
      context.registerShutdownHook();
   }
}
```

```markup
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="helloWorld" 
       class="com.yiibai.HelloWorld"
       init-method="init" destroy-method="destroy">
       <property name="message" value="Hello World!"/>
   </bean>

</beans>
```

Output:

```markup
Bean is going through init.
Your Message : Hello World!
Bean will destroy now.
```

### Dependency Injection

* By constructor&#x20;

```java
package x.y;

public class Foo {
   public Foo(Bar bar, Baz baz) {
      // ...
   }
}
```

```markup
<beans>
   <bean id="foo" class="x.y.Foo">
      <constructor-arg ref="bar"/>
      <constructor-arg ref="baz"/>
   </bean>

   <bean id="bar" class="x.y.Bar"/>
   <bean id="baz" class="x.y.Baz"/>
</beans>
```

* By setter

```java
package com.yiibai;

public class TextEditor {
   private SpellChecker spellChecker;

   // a setter method to inject the dependency.
   public void setSpellChecker(SpellChecker spellChecker) {
      System.out.println("Inside setSpellChecker." );
      this.spellChecker = spellChecker;
   }
   // a getter method to return spellChecker
   public SpellChecker getSpellChecker() {
      return spellChecker;
   }

   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}
```

```markup
<?xml version="1.0" encoding="UTF-8"?>
<? Method 1 ?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <!-- Definition for textEditor bean -->
   <bean id="textEditor" class="com.yiibai.TextEditor">
      <property name="spellChecker" ref="spellChecker"/>
   </bean>

   <!-- Definition for spellChecker bean -->
   <bean id="spellChecker" class="com.yiibai.SpellChecker">
   </bean>

</beans>
```

```markup
<?xml version="1.0" encoding="UTF-8"?>
<? Method 2 ?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <!-- Definition for textEditor bean using inner bean -->
   <bean id="textEditor" class="com.yiibai.TextEditor">
      <property name="spellChecker">
         <bean id="spellChecker" class="com.yiibai.SpellChecker"/>
       </property>
   </bean>

</beans>
```

### Auto Wire

#### By Type / By Name (XML)

```java
package com.yiibai;

public class TextEditor {
   private SpellChecker spellChecker;
   private String name;

   public void setSpellChecker( SpellChecker spellChecker ){
      this.spellChecker = spellChecker;
   }
   public SpellChecker getSpellChecker() {
      return spellChecker;
   }

   public void setName(String name) {
      this.name = name;
   }
   public String getName() {
      return name;
   }

   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}
```

```markup
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <!-- Definition for textEditor bean -->
   <bean id="textEditor" class="com.yiibai.TextEditor" 
      autowire="byType">
      <property name="name" value="Generic Text Editor" />
   </bean>

   <!-- Definition for spellChecker bean -->
   <bean id="spellChecker" class="com.yiibai.SpellChecker">
   </bean>

</beans>
```

* In text editor, it will look for the bean containing spell checker type or the same name automatically and inject into text editor

#### &#x20;By Type  (Annotation)

```java
package com.yiibai;

import org.springframework.beans.factory.annotation.Autowired;

public class TextEditor {
   private SpellChecker spellChecker;

   @Autowired
   public void setSpellChecker( SpellChecker spellChecker ){
      this.spellChecker = spellChecker;
   }
   
   public SpellChecker getSpellChecker( ) {
      return spellChecker;
   }
   
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}
```

* In text editor, it will look for the bean containing spell checker type automatically and inject into text editor
* If spellchecker is a interface , make sure that it should be implemented by one class only

#### &#x20;By Name (Annotation)

* If a spell checker may be a interface and implement by several class, so we should look for the bean according to the name of the bean

```java
package com.yiibai;

import org.springframework.beans.factory.annotation.Autowired;

public class TextEditor {
   private SpellChecker spellChecker;

   @Resource(name = "sampleSpellerChecker")
   public void setSpellChecker( SpellChecker spellChecker ){
      this.spellChecker = spellChecker;
   }
   
   public SpellChecker getSpellChecker( ) {
      return spellChecker;
   }
   
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}
```

### Configuration

In spring, we can make good use of annotation instead of configure xml file&#x20;

#### Annotation&#x20;

```java
package com.yiibai;

import org.springframework.context.annotation.*;

@Configuration
public class HelloWorldConfig {

   @Bean 
   public HelloWorld helloWorld(){
      return new HelloWorld();
   }
}
```

#### XML

```markup
<beans>
   <bean id="helloWorld" class="com.yiibai.HelloWorld" />
</beans>
```

## Component Scanning

### Introduction

* Initially, we need to declare each bean one by one. Now, we can make good use of annotation to mark the class as a component, and perform scanning on spring container which can be in xml or java code , that will register the bean automatically for class who is marked as a component

```java
@Configuration
@ComponentScan("com.luv2code")
@PropertySource("classpath:sport.properties")
public class SportConfig {
    @Bean
    public FortuneService normalFortuneService(){
        return new NormalFortuneService();
    }

    @Bean
    public Coach swimCoach(){
        return new SwimCoach(normalFortuneService());
    }
}
```

* There are common 5 annotations to create beans

### &#x20;Component

* It can be used in different layers&#x20;
* Not recommended to use

```java
@Component
public class UserComponentImpl implements IUser {
    private String name = "UserComponentImpl";

    public String get() {
        return name;
    }
}

@Component(value="componentBeanId")
public class UserComponentImplWithParam implements IUser {
    private String name = "UserComponentImplWithParam";

    public String get() {
        return name;
    }
}
```

```java
@SpringBootApplication
public class ComponentApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(ComponentApplication.class, args);
    
        IUser userComponentImpl1 = (UserComponentImpl)context.getBean("userComponentImpl");
        System.out.println(userComponentImpl1.get());
    
        IUser userComponentImpl2 = (UserComponentImplWithParam)context.getBean("componentBeanId");
        System.out.println(userComponentImpl2.get());
    }
}

// Output:
// UserComponentImpl
// UserComponentImplWithParam
```

### Service

* It is one part of the component
* Mainly responsible for the business logic
* In the most situation, it should be a interface and implemented by different class

```java
public interface TestService {
    public void test();
}
```

```java
@Service
@Scope("singleton")
public class TestServiceImpl implements TestService {
    @Override
    public void test(){
        ...
    }
}
```

### Repository&#x20;

* It is one part of the component
* Mainly responsible for visiting database and locate in the dao folder

```java
@Repository
public interface LocationRepository extends JpaRepository<Location,Integer> {
    List<Location> findByName(String name);
}
```

### Controller

* It is one part of the component
* used to handle URL and can used to return jsp file
* Example 1 (Return jsp File)

```java
@Controller
@RequestMapping("/test/{id}")
public class PathVariableTest {

    @RequestMapping("/{name}/get.do")
    public String get (@PathVariable("id") Integer index, Model model) {
        model.addAttribute("id", index);
        return "/index";
    }
}
```

* Example 2 (return string or other type)

```java
@Controller
@GetMapping("/bi")
public class ResponseBodyTest {

    @RequestMapping("/login")
    @ResponseBody
    public String get () {
        return "Hello Spring Boot!";
    }
}
```

### RestController

* It is one part of the controller
* act as a api end point and must be return in string or other type
* RestController = Controller + ResponseBody

```java
@RestController
@RequestMapping("/bi")
public class ResponseBodyTest {
    @GetMapping("/login") 
    public String get () {
        return "Hello Spring Boot!";
    }
}
```
