├── Dispatcher Servlet Flow.jpg ├── Dispatcher Servlet.png ├── README.md ├── Spring Framework - Coupling.png ├── Spring Framework - IoC.png ├── Spring Framework - Spring Boot.png └── Three Layer Architecture.png /Dispatcher Servlet Flow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onsever/spring-framework-notes/a9fbad476b5af59f810a9c3cc1228d67c0a9344c/Dispatcher Servlet Flow.jpg -------------------------------------------------------------------------------- /Dispatcher Servlet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onsever/spring-framework-notes/a9fbad476b5af59f810a9c3cc1228d67c0a9344c/Dispatcher Servlet.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Spring Framework Notes 3 | 4 | ## Author 5 | [Onurcan Sever](https://github.com/onsever) 6 | 7 | ## Jakarta EE vs J2EE vs Java EE 8 | * Jakarta EE (Jakarta Platform, Enterprise Edition) 9 | * Java EE (Java Platform, Enterprise Edition) 10 | * J2EE (Java 2 Platform, Enterprise Edition) 11 | 12 | ### Jakarta EE 13 | * Jakarta Server Pages (JSP): Used to create dynamic web pages. 14 | * Jakarta Standard Tag Library (JSTL): Used to show dynamic information on web pages. 15 | * Jakarta Enterprise Beans (EJB): Used to create enterprise applications. 16 | * Jakarta Restful Web Services (JAX-RS): Used to create RESTful web services. 17 | * Jakarta Bean Validation (JSR-303): Used to validate Java objects. 18 | * Jakarta Contexts and Dependency Injection (CDI): Used to inject dependencies into Java objects. 19 | * Jakarta Persistence (JPA): Used to persist Java objects into a database. 20 | * Jakarta Server Faces (JSF): Used to create user interfaces for web applications. 21 | * Jakarta Expression Language (EL): Used to evaluate expressions in Java applications. 22 | * Jakarta WebSocket: Used to create WebSocket applications. 23 | * Jakarta Batch: Used to create batch applications. 24 | * Jakarta Concurrency: Used to create concurrent applications. 25 | 26 | Spring 5 - Java EE (javax.*) 27 | Spring 6 - Jakarta EE (jakarta.*) 28 | 29 | ## Spring Framework 30 | Spring Framework is an open source Java platform that provides comprehensive infrastructure support for developing Java applications. Spring Framework is the most popular application framework for enterprise Java. Spring Framework is an open source framework for the Java platform. It is used to build Java enterprise applications. 31 | 32 | ### Tight Coupling vs Loose Coupling 33 | * **Tight Coupling:** When two classes are tightly coupled, they are dependent on each other. If one class changes, the other class will also change. 34 | 35 | * **Loose Coupling:** When two classes are loosely coupled, they are not dependent on each other. If one class changes, the other class will not change. 36 | 37 | In the example below, GameRunner class has a dependency on GamingConsole. Instead of wiring game object to a specific class such as MarioGame, we can use GamingConsole interface to make it loosely coupled. So that, we don't need to change our original code. In the future, we can create classes that implements GamingConsole interface (Polymorphism) and use it. 38 | 39 | ```java 40 | public class GameRunner { 41 | // public MarioGame game; // Tightly coupled to a specific game, so we need to change this. 42 | private final GamingConsole game; // Loosely coupled, it's not a specific game anymore. Games implement GamingConsole interface. Polymorphism. 43 | public GameRunner(GamingConsole game) { 44 | this.game = game; 45 | } 46 | 47 | public void run() { 48 | System.out.println("Running game: " + game); 49 | game.up(); 50 | game.down(); 51 | game.left(); 52 | game.right(); 53 | } 54 | } 55 | ``` 56 | 57 | ![diagram](https://github.com/onsever/spring-framework-notes/blob/main/Spring%20Framework%20-%20Coupling.png) 58 | 59 | ## Spring Container 60 | 61 | ### What is a Spring Container? 62 | Spring Container is the core of the Spring Framework. The Spring Container will create the objects, wire them together, configure them, and manage their complete life cycle from creation till destruction. The Spring Container uses DI to manage the components that make up an application. 63 | 64 | The Spring Container manages Spring beans and their life cycle. 65 | 66 | We have created POJOs (Plain Old Java Objects) and Configuration file. We passed them as inputs into Spring IoC Container. The Configuration file contains all of the beans. The output of Spring IoC Container is called Ready System. 67 | 68 | JVM (Java Virtual Machine) is the container that runs the Java application. Spring Container is the container that runs the Spring application. JVM contains Spring Context. 69 | 70 | Spring IoC container creates the runtime system for us. Creates Spring Context and manages beans for us. 71 | 72 | Spring Container—Spring Context—Spring IoC Container 73 | 74 | ### Different Types of IoC Containers 75 | Spring provides two types of IoC containers: 76 | * **BeanFactory Container:** Basic IoC container provided by Spring. It is the root interface for accessing a Spring BeanFactory. It is the simplest container provided by Spring. 77 | * **ApplicationContext Container:** It is the advanced container provided by Spring. It is built on top of the BeanFactory container. It adds more enterprise-specific functionality like the ability to resolve textual messages from a properties file and the ability to publish application events to interested event listeners. 78 | 79 | Most of the Spring applications use ApplicationContext container. It is recommended to use ApplicationContext container over BeanFactory container. (Web applications, web services, REST API and microservices) 80 | 81 | ### Diagram Example 82 | ![diagram](https://github.com/onsever/spring-framework-notes/blob/main/Spring%20Framework%20-%20IoC.png) 83 | 84 | ### Difference between Java Bean, POJO and Spring Bean 85 | 86 | #### POJO (Plain Old Java Object) 87 | - A POJO is a simple Java object, without any dependency. It does not extend any class and does not implement any interface. It is a simple Java object that is used to transfer data from one layer to another. 88 | - POJOs do not have any business logic. They are just simple data objects. 89 | - POJOs are not thread-safe. They are not synchronized. 90 | - POJOs do not have any dependency. They do not have any reference to any other object. 91 | 92 | #### Java Bean 93 | - A Java Bean is a POJO that follows some additional rules. 94 | - Java Beans are serializable. 95 | - Java Beans have a no-argument constructor. 96 | - Java Beans have getter and setter methods. 97 | - Java Beans are thread-safe. They are synchronized. 98 | - Java Beans have a dependency. They have a reference to other objects. 99 | 100 | #### Spring Bean 101 | - A Spring Bean is a POJO that is managed by Spring IoC Container (ApplicationContext or BeanFactory). 102 | 103 | ### Spring Bean Configuration 104 | Spring Bean Configuration is the process of defining beans. The Spring Bean Configuration can be done in two ways: 105 | * XML Based Configuration 106 | * Annotation Based Configuration 107 | 108 | ### How to list all beans managed by Spring Container? 109 | We can list all beans managed by Spring Container using the following code: 110 | ```java 111 | public class ExampleClass { 112 | public static void main(String[] args) { 113 | ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); 114 | 115 | String[] beanNames = context.getBeanDefinitionNames(); 116 | 117 | for (String beanName : beanNames) { 118 | System.out.println(beanName); 119 | } 120 | } 121 | } 122 | ``` 123 | 124 | ### What if multiple matching beans are found? 125 | If multiple matching beans are found, Spring will throw an exception. We can resolve this issue by using **@Qualifier** annotation. 126 | 127 | Another option is to use **@Primary** annotation. If we use **@Primary** annotation, Spring will use the bean that is marked with **@Primary** annotation if nothing else is specified. 128 | 129 | ### Primary vs Qualifier 130 | **@Primary** annotation is used to specify the default bean to be used when multiple beans are available. **@Qualifier** annotation is used to specify the bean to be used when multiple beans are available. 131 | 132 | ### What is the difference between @Component and @Bean? 133 | * **@Component** annotation is used to mark a class as a bean so that the component-scanning mechanism of Spring can pick it up and pull it into the application context. @Component annotation is used with classes that we have written. 134 | * **@Bean** annotation is used to mark a method as a bean so that the bean definition is generated and managed by the Spring container. @Bean annotation is used with methods that we have written. 135 | * **@Component** annotation is used with classes that we have written. 136 | * **@Bean** annotation is used with methods that we have written. 137 | 138 | ### Dependency Injection 139 | Dependency Injection is a design pattern that allows us to remove the hard-coded dependencies and make our code loosely coupled. It is a process whereby objects define their dependencies, that is, the other objects they work with, only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes, or a mechanism such as the Service Locator pattern. 140 | 141 | ### Constructor Injection 142 | 143 | #### Constructor Injection using @Autowired 144 | ```java 145 | public class Employee { 146 | private String name; private String email; 147 | @Autowired public Employee(String name, String email) { 148 | this.name = name; this.email = email; } 149 | } 150 | ``` 151 | 152 | #### Constructor Injection using @Autowired and @Qualifier 153 | ```java 154 | public class Employee { 155 | private String name; private String email; 156 | @Autowired public Employee(@Qualifier("name") String name, @Qualifier("email") String email) { 157 | this.name = name; this.email = email; } 158 | } 159 | ``` 160 | 161 | #### Constructor Injection using @Autowired and @Primary 162 | ```java 163 | public class Employee { 164 | private String name; private String email; 165 | @Autowired public Employee(@Primary String name, String email) { 166 | this.name = name; this.email = email; } 167 | } 168 | ``` 169 | 170 | ### Setter Injection 171 | ```java 172 | public class BusinessService { 173 | @Autowired 174 | public void setDataService(DataService dataService) { 175 | System.out.println("Setter injection"); 176 | this.dataService = dataService; 177 | } 178 | } 179 | ``` 180 | 181 | ### Field Injection 182 | ```java 183 | public class BusinessService { 184 | @Autowired 185 | private DataService dataService; 186 | } 187 | ``` 188 | 189 | ### Injection Example 190 | ```java 191 | @Component 192 | class YourBusinessClass { 193 | Dependency1 dependency1; 194 | // @Autowired // Field injection is not recommended 195 | Dependency2 dependency2; 196 | 197 | // Constructor injection -> Autowired is not necessary, it automatically injects dependencies. 198 | @Autowired 199 | public YourBusinessClass(Dependency1 dependency1, Dependency2 dependency2) { 200 | System.out.println("Constructor injection"); 201 | this.dependency1 = dependency1; 202 | this.dependency2 = dependency2; 203 | } 204 | 205 | @Override 206 | public String toString() { 207 | return "YourBusinessClass{" + 208 | "dependency1=" + dependency1 + 209 | ", dependency2=" + dependency2 + 210 | '}'; 211 | } 212 | 213 | // @Autowired // Setter injection 214 | public void setDependency1(Dependency1 dependency1) { 215 | System.out.println("Setter injection"); 216 | this.dependency1 = dependency1; 217 | } 218 | 219 | public void setDependency2(Dependency2 dependency2) { 220 | this.dependency2 = dependency2; 221 | } 222 | } 223 | ``` 224 | 225 | ### Inversion of Control (IoC) 226 | Inversion of Control (IoC) is a design principle in which the control of objects or portions of a program is transferred to a container or framework. Inversion of Control is a principle in software engineering by which the control of objects or portions of a program is transferred to a container or framework. The framework is responsible for managing the life cycle and the flow of control of the application. 227 | 228 | In regular programming, the control of objects is in the hands of the programmer. The programmer creates objects, wires them together, puts them into a configuration, and then the objects are ready to be used by the application. Inversion of Control reverses this process. The objects are created by a framework, and the framework wires them together and puts them into a configuration. The application then uses the objects from the framework. 229 | 230 | ### Dependency Injection (DI) 231 | Dependency Injection (DI) is a software design pattern that implements Inversion of Control for software applications. The basic idea behind DI is to provide the required dependencies to a class through external sources rather than creating them inside the class. This external source is called a container. The container is responsible for creating the dependencies and injecting them into the class. 232 | 233 | Example: 234 | ```java 235 | @Service 236 | public class BusinessCalculationService { 237 | 238 | // BusinessCalculationService depends on DataService. 239 | // BusinessCalculationService does not know which implementation of DataService is used. BusinessCalculationService needs to talk to DataService. 240 | // DataService is a dependency of BusinessCalculationService. 241 | private final DataService dataService; 242 | 243 | @Autowired // Constructor injection 244 | public BusinessCalculationService(DataService dataService) { 245 | super(); // Not necessary 246 | this.dataService = dataService; } 247 | 248 | public int findMax() { 249 | return Arrays.stream(dataService.retrieveData()).max().orElse(0); 250 | } 251 | } 252 | ``` 253 | 254 | ### Auto Wiring 255 | Auto Wiring is a process in which Spring automatically wires beans together by inspecting the beans and matching them with each other. 256 | 257 | ### Eager vs Lazy Initialization 258 | Eager initialization is the process of initializing a bean as soon as the Spring container is created. Lazy initialization is the process of initializing a bean when it is requested for the first time. 259 | 260 | The default Spring behaviour is Eager initialization. We can change the default behaviour to Lazy initialization by using **@Lazy** annotation. 261 | 262 | Eager initialization is the recommended approach. Because errors in the configuration are discovered immediately at application startup. We should use Lazy initialization only when we are sure that the bean will not be used. 263 | 264 | ```java 265 | @Component 266 | class ClassA {} 267 | 268 | @Component 269 | @Lazy // ClassB will be created and initialized when it is requested. It will not be created and initialized at startup. 270 | class ClassB { 271 | 272 | private final ClassA classA; 273 | 274 | // ClassB has a dependency on ClassA. 275 | @Autowired 276 | public ClassB(ClassA classA) { 277 | // Complex initialization logic goes here... 278 | // ClassB is using ClassA bean to initialize itself. 279 | System.out.println("Some initialization logic"); 280 | this.classA = classA; 281 | } 282 | 283 | public void doSomething() { 284 | System.out.println("Doing something"); 285 | } 286 | } 287 | 288 | @Configuration 289 | @ComponentScan("com.onurcansever.learnspringframework.examples.d1") 290 | public class LazyInitilizationLauncherApplication { 291 | public static void main(String[] args) { 292 | try(AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(LazyInitilizationLauncherApplication.class)){ 293 | // We have not requested ClassA bean (not calling it, not loading it); Spring is creating it and initializing it. 294 | // Even we have not requested ClassB bean (not calling it, not loading it); Spring is creating it and initializing it. To prevent this, we can use @Lazy annotation. Because by default, Spring creates and initializes all beans at startup. (Eager initialization) 295 | System.out.println("Initialization of context is completed."); 296 | 297 | // Initialization will happen when we request ClassB bean. (When somebody makes use of it) 298 | ClassB classB = context.getBean(ClassB.class); 299 | classB.doSomething(); 300 | } 301 | 302 | } 303 | } 304 | ``` 305 | 306 | ### Bean Scopes 307 | Bean Scopes are used to define the lifecycle of a bean. There are five different bean scopes in Spring: 308 | * Singleton 309 | * Prototype 310 | * Request 311 | * Session 312 | * Global Session 313 | 314 | ### Singleton Scope 315 | Singleton scope is the default scope of a bean. It means that only one instance of the bean will be created and shared among all the clients. 316 | 317 | It creates only one instance of the bean, and that instance is shared among all the clients. 318 | 319 | Stateless beans. (Doesn't hold user information) 320 | 321 | ### Prototype Scope 322 | Prototype scope means that a new instance of the bean will be created every time a request is made for the bean. 323 | 324 | It creates a new instance of the bean every time the bean is requested. 325 | 326 | Stateful beans. (Holds user information) 327 | 328 | To use Prototype scope, we need to use **@Scope** annotation with **@Component** annotation. 329 | 330 | ```java 331 | @Component 332 | @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) 333 | public class Employee { 334 | private String name; private String email;} 335 | ``` 336 | 337 | ```java 338 | @Configuration 339 | @ComponentScan 340 | public class BeanScopesLauncherApplication { 341 | 342 | public static void main(String[] args) { 343 | try(AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanScopesLauncherApplication.class)) { 344 | 345 | Arrays.stream(context.getBeanDefinitionNames()).forEach(System.out::println); 346 | 347 | // Singleton: The reference in memory is the same. It creates only one instance. (Hash code is the same) 348 | System.out.println(context.getBean(NormalClass.class)); 349 | System.out.println(context.getBean(NormalClass.class)); 350 | 351 | // Prototype: The reference in memory is different. It creates a new instance every time. (Hash code is different) 352 | System.out.println(context.getBean(PrototypeClass.class)); 353 | System.out.println(context.getBean(PrototypeClass.class)); 354 | System.out.println(context.getBean(PrototypeClass.class)); 355 | } 356 | } 357 | } 358 | ``` 359 | 360 | ### Request Scope 361 | Request scope means that a new instance of the bean will be created for each HTTP request. 362 | 363 | ### Session Scope 364 | Session scope means that a new instance of the bean will be created for each HTTP session. 365 | 366 | ### Global Session Scope 367 | Global Session scope means that a new instance of the bean will be created for each global HTTP session. 368 | 369 | ### Java Singleton (GOF) vs Spring Singleton 370 | * **Java Singleton** is a design pattern that restricts the instantiation of a class to one object. (One object instance per JVM) 371 | * **Spring Singleton** is a bean scope that restricts the instantiation of a bean to one object. (One object instance per Spring IoC Container) 372 | 373 | ### PostConstruct vs PreDestroy 374 | * **@PostConstruct** annotation is used on a method that needs to be executed after dependency injection is done to perform any initialization. (ex: Fetching data from a database) 375 | * **@PreDestroy** annotation is used on methods as a callback notification to signal that the instance is in the process of being removed by the container. (ex: Closing a database connection) 376 | 377 | ```java 378 | @Component 379 | class SomeClass { 380 | private final SomeDependency someDependency; 381 | 382 | @Autowired 383 | public SomeClass(SomeDependency someDependency) { 384 | super(); 385 | this.someDependency = someDependency; 386 | System.out.println("All dependencies are ready"); 387 | } 388 | 389 | // As soon as bean is created, dependencies are injected, and then this method is called by Spring Framework. 390 | @PostConstruct 391 | public void initialize() { 392 | someDependency.getReady(); 393 | } 394 | 395 | // Do something before bean is removed from the context and application is closed. 396 | @PreDestroy 397 | public void cleanUp() { 398 | System.out.println("Cleaning up"); 399 | } 400 | 401 | } 402 | ``` 403 | 404 | ### Jakarta Contexts and Dependency Injection (CDI) 405 | Jakarta Contexts and Dependency Injection (CDI) is a standard for dependency injection and contextual lifecycle management for Java EE applications. It is a part of Jakarta EE. Spring Framework implements CDI specification. 406 | 407 | * Named: **@Named** -> @Named("name") is used to specify the name of the bean. Alternatively, we can use @Component annotation. 408 | * Inject: **@Inject** -> @Inject is used to inject a dependency. Alternatively, we can use @Autowired annotation. 409 | * Qualifier: **@Qualifier** -> @Qualifier("name") is used to specify the name of the bean. Alternatively, we can use @Qualifier annotation. 410 | * Scope: **@Scope** -> @Scope("name") is used to specify the scope of the bean. Alternatively, we can use @Scope annotation. 411 | 412 | Add following as a dependency to the `pom.xml` file. 413 | 414 | ```xml 415 | 416 | jakarta.inject 417 | jakarta.inject-api 418 | 2.0.1 419 | 420 | ``` 421 | 422 | ```java 423 | // @Component 424 | @Named 425 | class BusinessService { 426 | private DataService dataService; 427 | 428 | public DataService getDataService() { 429 | return dataService; 430 | } 431 | 432 | // @Autowired 433 | @Inject 434 | public void setDataService(DataService dataService) { 435 | System.out.println("Setter injection"); 436 | this.dataService = dataService; 437 | } 438 | } 439 | ``` 440 | 441 | ### Spring XML Configuration 442 | Spring XML Configuration is a way of configuring Spring beans using XML files. We can configure beans using XML files instead of using annotations. 443 | 444 | Steps to configure Spring beans using XML files: 445 | 1. Create a Spring configuration file (ex: `beans.xml`) under `src/main/resources` folder. 446 | 2. Add the following XML code to the `beans.xml` file. 447 | 448 | ```xml 449 | 450 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | ``` 461 | 462 | * **constructor-arg** tag is used to inject a dependency to a constructor. 463 | * **property tag** is used to inject a dependency to a setter method. 464 | * **context:component-scan** tag is used to scan for components. 465 | 466 | To make use of the Spring configuration file, we need to add the following code to the main method. 467 | 468 | ```java 469 | public class XmlExample { 470 | public static void main(String[] args) { 471 | ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); 472 | Employee employee = context.getBean("employee", Employee.class); 473 | System.out.println(employee); 474 | context.close(); 475 | } 476 | } 477 | ``` 478 | 479 | ### Spring Stereotype Annotations 480 | * **@Component**: @Component is a generic stereotype for any Spring-managed component. It is a general-purpose annotation. It is a meta-annotation that serves as a specialization of @Component for different use cases. 481 | * **@Service:** @Service is a specialization of @Component for service layer. Indicates that an annotated class has **business logic**. 482 | * **@Controller:** @Controller is a specialization of @Component for presentation layer. Indicates that an annotated class is a "Controller" (e.g. a web controller, REST API). 483 | * **@Repository:** @Repository is a specialization of @Component for persistence layer. Indicates that an annotated class is a "Repository" (e.g. a DAO). Used to retrieve and/or manipulate data from a database. 484 | 485 | #### Why? 486 | * Giving more information to the framework about our intentions. 487 | * We can use AOP at a later point to add additional behaviour such as: for @Repository, Spring framework automatically wires in JDBC exception translation. (ex: SQLException -> DataAccessException) 488 | 489 | ```java 490 | @Service 491 | public class BusinessCalculationService { 492 | 493 | // BusinessCalculationService depends on DataService. 494 | // BusinessCalculationService does not know which implementation of DataService is used. BusinessCalculationService needs to talk to DataService. 495 | // DataService is a dependency of BusinessCalculationService. 496 | private final DataService dataService; 497 | 498 | @Autowired // Constructor injection 499 | public BusinessCalculationService(DataService dataService) { 500 | super(); // Not necessary 501 | this.dataService = dataService; 502 | } 503 | 504 | public int findMax() { 505 | return Arrays.stream(dataService.retrieveData()).max().orElse(0); 506 | } 507 | } 508 | ``` 509 | 510 | ### Spring Big Picture - Framework, Modules and Projects 511 | * **Spring Core:** IoC Container, Dependency Injection, Auto Wiring... (Building web applications, creating REST API, implementing authentication and authorization, talking to a database, integrating with other systems, writing great unit tests, etc.) 512 | 513 | The Spring Framework contains multiple Spring Modules: 514 | * **Fundamental Features:** Core (IoC Container, Dependency Injection, Auto Wiring) 515 | * **Web:** Spring MVC (Web Applications, REST API) 516 | * **Web Reactive:** Spring WebFlux 517 | * **Data Access:** JDBC, JPA etc. 518 | * **Integration:** JMS etc. 519 | * **Testing:** Mock Objects, Spring MVC Test etc. 520 | 521 | #### Why is Spring Framework divided into multiple modules? 522 | * Each application can choose modules that it needs. 523 | * Application doesn't need to use every module. 524 | 525 | ### Spring Projects 526 | * Application architectures evolve continuously: 527 | * Web > Rest API > Microservices > Cloud > ... 528 | * Spring evolves through Spring Projects: 529 | * **First Project:** Spring Framework 530 | * **Spring Security:** Secure your web application or REST API or microservice. 531 | * **Spring Data:** Integrate the same way with different types of databases: NoSQL and Relational. 532 | * **Spring Integration:** Address challenges with integration with other applications. 533 | * **Spring Boot:** Popular framework to build microservices. 534 | * **Spring Cloud:** Build cloud-native applications. 535 | 536 | ### Why is Spring Ecosystem popular? 537 | * **Loose Coupling:** Spring manages creating and wiring of beans and dependencies. It makes it maintainable and writing unit tests easily. 538 | * **Reduced Boilerplate Code:** Spring provides a lot of annotations to reduce boilerplate code. No exception handling. 539 | * **Architectural Flexibility:** Spring Modules and Projects. 540 | * **Evolution with Time:** Microservices and Cloud. (Spring Boot, Spring Cloud etc.) 541 | 542 | ## Extra Notes 543 | ```text 544 | // Performs scan for components in the same package (if we don't specify basePackages, it will scan the package of the class) 545 | @ComponentScan 546 | ``` 547 | 548 | ```text 549 | // Tell Spring where to search for beans (components) -> package 550 | @ComponentScan(basePackages = "com.onurcansever.learnspringframework.game") 551 | ``` 552 | 553 | --- 554 | 555 | # Spring Boot Notes 556 | 557 | ## Goal of Spring Boot 558 | * Help us to build production-ready applications quickly. 559 | 560 | ### Quickly 561 | * **Spring Initializr** 562 | * **Spring Boot Starter Projects:** Quickly define dependencies. 563 | * **Spring Boot Auto Configuration:** Automatically provide configuration based on dependencies in the class. 564 | * **Spring Boot DevTools:** Help us to make changes to the application without restarting the application. 565 | 566 | To add Spring Boot DevTools to the project, add the following dependency to the `pom.xml` file: 567 | ```xml 568 | 569 | org.springframework.boot 570 | spring-boot-devtools 571 | runtime 572 | true 573 | 574 | ``` 575 | 576 | If we change anything in pom.xml, we need to restart manually. 577 | 578 | ### Production-ready 579 | * Logging 580 | * Different Configurations for Different Environments (Profiles, ConfigurationProperties) 581 | * Monitoring (Spring Boot Actuator) 582 | 583 | #### Managing Application Configuration using Profiles 584 | * Application have different environments: development, test, production. 585 | * A different environment needs different configurations for the same application. (Different databases, different web service, etc.) 586 | * Profiles allow us to define different configurations for different environments. 587 | 588 | ```text 589 | We can create separate application.properties files and configurations for each environment. 590 | 591 | dev: 592 | logging.level.org.springframework=trace 593 | qa 594 | stage 595 | prod: 596 | logging.level.org.springframework=info 597 | ``` 598 | 599 | For example, to create a profile for development environment, we can create a file named `application-dev.properties` in the `src/main/resources` folder. 600 | 601 | ```text 602 | logging.level.org.springframework=trace 603 | ``` 604 | 605 | By default, Spring Boot uses the `application.properties` file. To use the `application-dev.properties` file, we need to specify the profile in the `application.properties` file. 606 | 607 | ```text 608 | spring.profiles.active=dev 609 | ``` 610 | 611 | Values from the default configuration and the profile-specific configuration are merged. If there is a conflict, the profile-specific configuration wins. 612 | 613 | #### Spring Boot Starter Projects 614 | * We need a lot of frameworks to build a web application. 615 | * For example, building a REST API, we need: Spring, Spring MVC, Tomcat, JSON conversion (from the Java list of courses to JSON list) etc. 616 | * Writing unit tests, we need: JUnit, Mockito, Spring Test etc. 617 | 618 | #### Spring Boot Configuration Properties 619 | Setting up complex configuration example: 620 | 621 | Inside the `application.properties` file, we can define the following properties: 622 | 623 | ```text 624 | currency-service.url= 625 | currency-service.username= 626 | currency-service.key= 627 | ``` 628 | 629 | #### How does Spring Boot help us manage application configuration? How can we define a property value and use it in the application? 630 | * If we want to create a lot of application configurations, we can create a separate class for each configuration called ConfigurationProperties. 631 | 632 | ```java 633 | import org.springframework.boot.context.properties.ConfigurationProperties; 634 | import org.springframework.stereotype.Component; 635 | 636 | // Mapped to the properties file. 637 | @ConfigurationProperties(prefix = "currency-service") // Prefix@Component 638 | public class CurrencyServiceConfiguration { 639 | 640 | private String url; private String username; private String key; 641 | public String getUrl() { 642 | return url; } 643 | 644 | public void setUrl(String url) { 645 | this.url = url; } 646 | 647 | public String getUsername() { 648 | return username; } 649 | 650 | public void setUsername(String username) { 651 | this.username = username; } 652 | 653 | public String getKey() { 654 | return key; } 655 | 656 | public void setKey(String key) { 657 | this.key = key; } 658 | } 659 | ``` 660 | 661 | * We can also override the default configuration in another profile. For example, in the `application-dev.properties` file, we can override the default configuration. 662 | 663 | ```text 664 | currency-service.url=http://dev.example.com 665 | currency-service.username=devusername 666 | currency-service.key=devkey 667 | ``` 668 | 669 | ### Simply Deployment with Spring Boot Embedded Servers 670 | * We need to simplify the deployment of our application because we have multiple environments such as development, test, production, etc. *(Make JAR not WAR)* 671 | 672 | Clean Maven Build: 673 | ```bash 674 | mvn clean install 675 | ``` 676 | 677 | Run the application: 678 | ```bash 679 | java -jar target/spring-boot-0.0.1-SNAPSHOT.jar 680 | ``` 681 | 682 | File path: 683 | ```text 684 | /Users/admin/Desktop/java-spring-boot-udemy/learn-spring-boot/target/ 685 | learn-spring-boot-0.0.1-SNAPSHOT.jar 686 | ``` 687 | 688 | ### Monitor Applications using Spring Boot Actuator 689 | * Monitor and manage our application in production. 690 | * Provides a number of endpoints: 691 | * **beans:** Complete list of Spring beans in the application. 692 | * **health:** Application health information. 693 | * **metrics:** Application metrics information. 694 | * **mappings:** Details around Request Mappings. 695 | 696 | #### How to add Spring Boot Actuator to the project? 697 | * Add the following dependency to the `pom.xml` file: 698 | ```xml 699 | 700 | org.springframework.boot 701 | spring-boot-starter-actuator 702 | 703 | ``` 704 | 705 | #### How to access the endpoints? 706 | * We can access the endpoints using the following URL: 707 | ```text 708 | http://localhost:8080/actuator 709 | ``` 710 | 711 | We can add more features by enabling the following properties in the `application.properties` file: 712 | ```text 713 | management.endpoints.web.exposure.include=* 714 | ``` 715 | 716 | If we include lots of endpoints, it will consume *more CPU and memory*. So, we can include only the endpoints that we need. 717 | 718 | ```text 719 | management.endpoints.web.exposure.include=beans,health,info 720 | ``` 721 | 722 | ### Three Layer Architecture 723 | ![diagram](https://github.com/onsever/spring-framework-notes/blob/main/Three%20Layer%20Architecture.png) 724 | 725 | ### Spring Boot vs Spring MVC vs Spring 726 | * **Spring Framework:** Dependency Injection and other Spring framework features. 727 | (Spring Modules and Spring Projects) 728 | * **Spring MVC (Spring Module):** Simplify the development of web applications and RESTful web services. (@Controller, @RestController, @RequestMapping) 729 | * **Spring Boot (Spring Project):** Quickly build production-ready applications. (Starter projects and autoconfiguration) 730 | * Enables non functional requirements (NFRs): 731 | * Embedded Servers 732 | * Actuator 733 | * Logging and Error Handling 734 | * Profiles and Configuration Properties 735 | 736 | ![diagram](https://github.com/onsever/spring-framework-notes/blob/main/Spring%20Framework%20-%20Spring%20Boot.png) 737 | 738 | --- 739 | 740 | # Spring JDBC, H2 Database, Hibernate, JPA Notes 741 | 742 | * H2 Database: In-memory database. 743 | * Connection to H2 Database: `conn0: url=jdbc:h2:mem:bdfa2bb8-4131-4dce-96c4-550927009ec5 user=SA` 744 | * In `application.properties`, set `spring.h2.console.enabled=true` 745 | * To access console, go to `http://localhost:8080/h2-console/` 746 | * Copy and paste `jdbc:h2:mem:f30911dd-9715-4a83-9d4a-880d582be6a7` into JDBC URL. This is a dynamic URL which changes every restart. We can configure static URL. 747 | * To configure static URL, add `spring.datasource.url=jdbc:h2:mem:testdb` in `application.properties`. This will create a database called `testdb` in memory. 748 | 749 | If we want to use JDBC, JPA, Spring Data JPA, Hibernate etc. To do that, we need to create tables in the H2 database. 750 | 751 | We need to create a file called `schema.sql` in `src/main/resources` folder. This file will contain the SQL statements to create the tables. 752 | 753 | ```sql 754 | CREATE TABLE course 755 | ( 756 | id BIGINT NOT NULL, 757 | name VARCHAR(255) NOT NULL, 758 | author VARCHAR(255) NOT NULL, 759 | PRIMARY KEY (id) 760 | ); 761 | ``` 762 | 763 | ## JDBC (Java Database Connectivity) 764 | * JDBC is a Java API to connect to a database. 765 | * Write a lot of SQL queries. 766 | * More Java code. 767 | 768 | ## Spring JDBC 769 | * Spring JDBC is a framework that provides a simple, lightweight, and fast way to access the database. 770 | * Write a lot of SQL queries. 771 | * Lesser Java code. 772 | 773 | We will execute the code below using Spring JDBC. 774 | 775 | ```sql 776 | INSERT INTO course (id, name, author) 777 | VALUES (1, 'Learn AWS', 'Onur'); 778 | 779 | SELECT * FROM course; 780 | 781 | DELETE FROM course WHERE id = 1; 782 | ``` 783 | 784 | ```java 785 | @Repository // Class talks to a database. 786 | public class CourseJdbcRepository { 787 | // To run queries using Spring JDBC, we need to use JdbcTemplate. 788 | 789 | @Autowired // Spring will inject the JdbcTemplate object. 790 | private JdbcTemplate springJdbcTemplate; 791 | private static String INSERT_QUERY = 792 | """ 793 | INSERT INTO course (id, name, author) 794 | VALUES (?, ?, ?); 795 | """; 796 | 797 | private static String DELETE_QUERY = 798 | """ 799 | DELETE FROM course 800 | WHERE id = ?; 801 | """; 802 | 803 | private static String SELECT_QUERY = 804 | """ 805 | SELECT * FROM course 806 | WHERE id = ?; 807 | """; 808 | 809 | public void insert(Course course) { 810 | springJdbcTemplate.update(INSERT_QUERY, course.getId(), course.getName(), course.getAuthor()); // Insert, Update, Delete 811 | } 812 | 813 | public void deleteById(long id) { 814 | springJdbcTemplate.update(DELETE_QUERY, id); 815 | } 816 | 817 | public Course findById(long id) { 818 | // Single Row 819 | // ResultSet -> Bean => Row Mapper 820 | return springJdbcTemplate.queryForObject(SELECT_QUERY, new BeanPropertyRowMapper<>(Course.class), id); 821 | 822 | // When we execute SELECT_QUERY, we need to map it because SELECT_QUERY returns multiple rows. (Kind of like a table) -> RowMapper 823 | 824 | // Take the ResultSet and map it to the Course bean. -> RowMapper (They map each row in the ResultSet to a bean.) 825 | 826 | // If we get null values, we need to add Setters to the Course class. 827 | } 828 | } 829 | 830 | ``` 831 | 832 | ## JPA (Java Persistence API) 833 | * JPA is a Java API to connect to a database. 834 | * Map Entities to Tables. 835 | * Make use of EntityManager. 836 | 837 | ```java 838 | @Repository // Class talks to a database. 839 | @Transactional // We want to make use of JPA, so we need to use @Transactional. 840 | public class CourseJpaRepository { 841 | // If we want to make use JPA talk to the database, we need to use EntityManager. 842 | 843 | // @Autowired // Spring will inject the EntityManager object. 844 | @PersistenceContext // PersistenceContext is a better way to inject the EntityManager object. 845 | private EntityManager entityManager; 846 | 847 | public void insert(Course course) { 848 | entityManager.merge(course); // Insert a row. 849 | } 850 | 851 | public Course findById(long id) { 852 | // We want to find Course, so we pass Course.class as the first parameter. 853 | return entityManager.find(Course.class, id); // Find a row. 854 | } 855 | 856 | public void deleteById(long id) { 857 | Course course = entityManager.find(Course.class, id); 858 | entityManager.remove(course); // Delete a row. 859 | } 860 | } 861 | 862 | ``` 863 | 864 | ## Spring Data JPA 865 | * Spring Data JPA is a framework that provides a simple, lightweight, and fast way to access the database. 866 | * It makes JPA easy to use. It configures EntityManager. 867 | 868 | ```java 869 | // This is a Spring Data JPA Repository 870 | // We need to create an interface and extend JpaRepository. 871 | // We need to pass the entity class (Course) and the primary key type. 872 | public interface CourseSpringDataJpaRepository extends JpaRepository { 873 | // We can add custom methods to this interface. 874 | // Spring Data JPA will implement these methods. 875 | // Spring Data JPA will create a proxy object for this interface. 876 | 877 | // Search by author. 878 | // Follow naming conventions. We are searching by author, so we need to name the method findByAuthor. 879 | List findByAuthor(String author); 880 | List findByName(String name); 881 | } 882 | 883 | ``` 884 | 885 | ## Hibernate vs JPA 886 | * JPA is a specification. It is an API. (How to define entities, How to map attributes, Who manage the entities) 887 | * Hibernate is an implementation of JPA. 888 | * Using Hibernate will lock us to Hibernate. We cannot use other implementations of JPA. (Toplink, EclipseLink, OpenJPA) 889 | 890 | ## Executing Queries using CommandLineRunner 891 | 892 | ```java 893 | @Component // This class is a Spring Bean. 894 | public class CourseCommandLineRunner implements CommandLineRunner { 895 | // We want to execute this query at the start of the application. To do that, we need to create a CommandLineRunner. 896 | // We need to implement the run method of CommandLineRunner. 897 | // We need to create a Spring Bean of this class. To do that, we need to add @Component annotation. 898 | // We need to create a CourseJdbcRepository object. 899 | 900 | // @Autowired 901 | // private CourseJpaRepository repository; 902 | 903 | @Autowired // Spring will inject the CourseSpringDataJpaRepository object. 904 | private CourseSpringDataJpaRepository repository; 905 | 906 | // Using Spring Data JPA, EntityManager is handled by Spring Data JPA. 907 | 908 | @Override 909 | public void run(String... args) throws Exception { 910 | repository.save(new Course(1, "Learn AWS", "Onur")); // Insert or Update 911 | repository.save(new Course(2, "Learn Azure", "Onur")); 912 | repository.save(new Course(3, "Learn DevOps", "Onur")); 913 | repository.save(new Course(4, "Learn Docker", "Onur")); 914 | 915 | repository.deleteById(1l); 916 | 917 | System.out.println(repository.findById(2l)); 918 | System.out.println(repository.findById(3l)); 919 | 920 | repository.findAll().forEach(System.out::println); 921 | System.out.println(repository.count()); 922 | 923 | System.out.println(repository.findByAuthor("Onur")); 924 | System.out.println(repository.findByName("Learn Docker Now")); 925 | } 926 | } 927 | 928 | /* 929 | @Component // This class is a Spring Bean. 930 | public class CourseJdbcCommandLineRunner implements CommandLineRunner { 931 | // We want to execute this query at the start of the application. To do that, we need to create a CommandLineRunner. 932 | // We need to implement the run method of CommandLineRunner. 933 | // We need to create a Spring Bean of this class. To do that, we need to add @Component annotation. 934 | // We need to create a CourseJdbcRepository object. 935 | 936 | @Autowired // Spring will inject the CourseJdbcRepository object. 937 | private CourseJdbcRepository repository; 938 | 939 | @Override 940 | public void run(String... args) throws Exception { 941 | repository.insert(new Course(1, "Learn AWS", "Onur")); 942 | repository.insert(new Course(2, "Learn Azure", "Onur")); 943 | repository.insert(new Course(3, "Learn DevOps", "Onur")); 944 | 945 | repository.deleteById(1); 946 | 947 | System.out.println(repository.findById(2)); 948 | System.out.println(repository.findById(3)); 949 | } 950 | } 951 | */ 952 | ``` 953 | 954 | # How Dispatcher Servlet Works Behind the Scenes 955 | ![diagram](https://github.com/onsever/spring-framework-notes/blob/main/Dispatcher%20Servlet.png) 956 | -------------------------------------------------------------------------------- /Spring Framework - Coupling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onsever/spring-framework-notes/a9fbad476b5af59f810a9c3cc1228d67c0a9344c/Spring Framework - Coupling.png -------------------------------------------------------------------------------- /Spring Framework - IoC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onsever/spring-framework-notes/a9fbad476b5af59f810a9c3cc1228d67c0a9344c/Spring Framework - IoC.png -------------------------------------------------------------------------------- /Spring Framework - Spring Boot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onsever/spring-framework-notes/a9fbad476b5af59f810a9c3cc1228d67c0a9344c/Spring Framework - Spring Boot.png -------------------------------------------------------------------------------- /Three Layer Architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onsever/spring-framework-notes/a9fbad476b5af59f810a9c3cc1228d67c0a9344c/Three Layer Architecture.png --------------------------------------------------------------------------------