├── 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 | 
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 | 
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 | 
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 | 
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 | 
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
--------------------------------------------------------------------------------