Step 1 - Setting up a Spring Project using htttp://start.spring.io
Step 2 - Understanding Tight Coupling using the Binary Search Algorithm Example
Step 3 - Making the Binary Search Algorithm Example Loosely Coupled
Step 4 - Using Spring to Manage Dependencies - @Component, @Autowired
Step 5 - What is happening in the background?
Step 6 - Dynamic auto wiring and Troubleshooting - @Primary
Step 7 - Constructor and Setter Injection
Step 8 - Spring Modules
Step 9 - Spring Projects
Step 10 - Why is Spring Popular?
Step 11 - Dependency Injection - A few more examples
Step 12 - Autowiring in Depth - by Name and @Primary
Step 13 - Autowiring in Depth - @Qualifier annotation
Step 14 - Scope of a Bean - Prototype and Singleton
Step 15 - Complex scenarios with Scope of a Spring Bean - Mix of Prototype and Singleton
Step 15B - Difference Between Spring Singleton and GOF Singleton
Step 16 - Using Component Scan to scan for beans
Step 17 - Lifecycle of a Bean - @PostConstruct and @PreDestroy
Step 18 - Container and Dependency Injection (CDI) - @Named, @Inject
Step 19 - Removing Spring Boot in Basic Application
Step 20 - Fixing minor stuff - Add Logback and Close Application Context
Step 21 - Defining Spring Application Context using XML - Part 1
Step 22 - Defining Spring Application Context using XML - Part 2
Step 23 - Mixing XML Context with Component Scan for Beans defined with Annotations
Step 24 - IOC Container vs Application Context vs Bean Factory
Step 25 - @Component vs @Service vs @Repository vs @Controller
Step 26 - Read values from external properties file
Step 27 - Spring Unit Testing with a Java Context
Step 28 - Spring Unit Testing with an XML Context
Step 29 - Spring Unit Testing with Mockito
[componentDAO, scopedTarget.componentJdbcConnection,
componentJdbcConnection, springIn5StepsBasicApplication,
springIn5StepsCdiApplication,
springIn5StepsComponentScanApplication, springIn5StepsScopeApplication,
binarySearchImpl, bubbleSortAlgorithm, quickSortAlgorithm,
someCdiBusiness, someCdiDao, scopedTarget.jdbcConnection,
jdbcConnection, personDAO, org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalRequiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory,
xmlJdbcConnection, xmlPersonDAO]
<?xml version =" 1.0" encoding =" UTF-8" ?>
<project xmlns =" http://maven.apache.org/POM/4.0.0" xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion >4.0.0</modelVersion >
<groupId >com.in28minutes.spring.basics</groupId >
<artifactId >spring-in-5-steps</artifactId >
<version >0.0.1-SNAPSHOT</version >
<packaging >jar</packaging >
<name >spring-in-5-steps</name >
<description >Demo project for Spring Boot</description >
<parent >
<groupId >org.springframework.boot</groupId >
<artifactId >spring-boot-starter-parent</artifactId >
<version >2.0.0.RELEASE</version >
<relativePath /> <!-- lookup parent from repository -->
</parent >
<properties >
<project .build.sourceEncoding>UTF-8</project .build.sourceEncoding>
<project .reporting.outputEncoding>UTF-8</project .reporting.outputEncoding>
<java .version>1.8</java .version>
</properties >
<dependencies >
<dependency >
<groupId >org.springframework</groupId >
<artifactId >spring-core</artifactId >
</dependency >
<dependency >
<groupId >org.springframework</groupId >
<artifactId >spring-context</artifactId >
</dependency >
<dependency >
<groupId >org.slf4j</groupId >
<artifactId >slf4j-api</artifactId >
</dependency >
<dependency >
<groupId >ch.qos.logback</groupId >
<artifactId >logback-classic</artifactId >
</dependency >
<dependency >
<groupId >javax.inject</groupId >
<artifactId >javax.inject</artifactId >
<version >1</version >
</dependency >
<dependency >
<groupId >org.springframework.boot</groupId >
<artifactId >spring-boot-starter-test</artifactId >
<scope >test</scope >
</dependency >
</dependencies >
<build >
<plugins >
<plugin >
<groupId >org.springframework.boot</groupId >
<artifactId >spring-boot-maven-plugin</artifactId >
</plugin >
</plugins >
</build >
<repositories >
<repository >
<id >spring-snapshots</id >
<name >Spring Snapshots</name >
<url >https://repo.spring.io/snapshot</url >
<snapshots >
<enabled >true</enabled >
</snapshots >
</repository >
<repository >
<id >spring-milestones</id >
<name >Spring Milestones</name >
<url >https://repo.spring.io/milestone</url >
<snapshots >
<enabled >false</enabled >
</snapshots >
</repository >
</repositories >
<pluginRepositories >
<pluginRepository >
<id >spring-snapshots</id >
<name >Spring Snapshots</name >
<url >https://repo.spring.io/snapshot</url >
<snapshots >
<enabled >true</enabled >
</snapshots >
</pluginRepository >
<pluginRepository >
<id >spring-milestones</id >
<name >Spring Milestones</name >
<url >https://repo.spring.io/milestone</url >
<snapshots >
<enabled >false</enabled >
</snapshots >
</pluginRepository >
</pluginRepositories >
</project >
/src/main/java/com/in28minutes/spring/basics/componentscan/ComponentDAO.java
package com .in28minutes .spring .basics .componentscan ;
import org .springframework .beans .factory .annotation .Autowired ;
import org .springframework .stereotype .Repository ;
@ Repository
public class ComponentDAO {
@ Autowired
ComponentJdbcConnection jdbcConnection ;
public ComponentJdbcConnection getJdbcConnection () {
return jdbcConnection ;
}
public void setComponentJdbcConnection (ComponentJdbcConnection jdbcConnection ) {
this .jdbcConnection = jdbcConnection ;
}
}
/src/main/java/com/in28minutes/spring/basics/componentscan/ComponentJdbcConnection.java
package com .in28minutes .spring .basics .componentscan ;
import org .springframework .beans .factory .config .ConfigurableBeanFactory ;
import org .springframework .context .annotation .Scope ;
import org .springframework .context .annotation .ScopedProxyMode ;
import org .springframework .stereotype .Component ;
@ Component
@ Scope (value =ConfigurableBeanFactory .SCOPE_PROTOTYPE ,
proxyMode = ScopedProxyMode .TARGET_CLASS )
public class ComponentJdbcConnection {
public ComponentJdbcConnection () {
System .out .println ("JDBC Connection" );
}
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/basic/BinarySearchImpl.java
package com .in28minutes .spring .basics .springin5steps .basic ;
import javax .annotation .PostConstruct ;
import javax .annotation .PreDestroy ;
import org .slf4j .Logger ;
import org .slf4j .LoggerFactory ;
import org .springframework .beans .factory .annotation .Autowired ;
import org .springframework .beans .factory .annotation .Qualifier ;
import org .springframework .beans .factory .config .ConfigurableBeanFactory ;
import org .springframework .context .annotation .Scope ;
import org .springframework .stereotype .Component ;
import org .springframework .stereotype .Service ;
@ Service
@ Scope (ConfigurableBeanFactory .SCOPE_SINGLETON )
public class BinarySearchImpl {
private Logger logger = LoggerFactory .getLogger (this .getClass ());
@ Autowired
@ Qualifier ("bubble" )
private SortAlgorithm sortAlgorithm ;
public int binarySearch (int [] numbers , int numberToSearchFor ) {
int [] sortedNumbers = sortAlgorithm .sort (numbers );
System .out .println (sortAlgorithm );
// Search the array
return 3 ;
}
@ PostConstruct
public void postConstruct () {
logger .info ("postConstruct" );
}
@ PreDestroy
public void preDestroy () {
logger .info ("preDestroy" );
}
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/basic/BubbleSortAlgorithm.java
package com .in28minutes .spring .basics .springin5steps .basic ;
import org .springframework .beans .factory .annotation .Qualifier ;
import org .springframework .stereotype .Component ;
import org .springframework .stereotype .Service ;
@ Service
@ Qualifier ("bubble" )
public class BubbleSortAlgorithm implements SortAlgorithm {
public int [] sort (int [] numbers ) {
// Logic for Bubble Sort
return numbers ;
}
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/basic/QuickSortAlgorithm.java
package com .in28minutes .spring .basics .springin5steps .basic ;
import org .springframework .beans .factory .annotation .Qualifier ;
import org .springframework .stereotype .Service ;
@ Service
@ Qualifier ("quick" )
public class QuickSortAlgorithm implements SortAlgorithm {
public int [] sort (int [] numbers ) {
// Logic for Quick Sort
return numbers ;
}
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/basic/SortAlgorithm.java
package com .in28minutes .spring .basics .springin5steps .basic ;
public interface SortAlgorithm {
public int [] sort (int [] numbers );
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/cdi/SomeCdiBusiness.java
package com .in28minutes .spring .basics .springin5steps .cdi ;
import javax .inject .Inject ;
import javax .inject .Named ;
@ Named
public class SomeCdiBusiness {
@ Inject
SomeCdiDao someCdiDao ;
public SomeCdiDao getSomeCDIDAO () {
return someCdiDao ;
}
public void setSomeCDIDAO (SomeCdiDao someCdiDao ) {
this .someCdiDao = someCdiDao ;
}
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/cdi/SomeCdiDao.java
package com .in28minutes .spring .basics .springin5steps .cdi ;
import javax .inject .Named ;
@ Named
public class SomeCdiDao {
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/properties/SomeExternalService.java
package com .in28minutes .spring .basics .springin5steps .properties ;
import org .springframework .beans .factory .annotation .Value ;
import org .springframework .stereotype .Component ;
@ Component
public class SomeExternalService {
@ Value ("${external.service.url}" )
private String url ;
public String returnServiceURL (){
return url ;
}
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/scope/JdbcConnection.java
package com .in28minutes .spring .basics .springin5steps .scope ;
import org .springframework .beans .factory .config .ConfigurableBeanFactory ;
import org .springframework .context .annotation .Scope ;
import org .springframework .context .annotation .ScopedProxyMode ;
import org .springframework .stereotype .Component ;
@ Component
@ Scope (value =ConfigurableBeanFactory .SCOPE_PROTOTYPE ,
proxyMode = ScopedProxyMode .TARGET_CLASS )
public class JdbcConnection {
public JdbcConnection () {
System .out .println ("JDBC Connection" );
}
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/scope/PersonDAO.java
package com .in28minutes .spring .basics .springin5steps .scope ;
import org .springframework .beans .factory .annotation .Autowired ;
import org .springframework .stereotype .Repository ;
@ Repository
public class PersonDAO {
@ Autowired
JdbcConnection jdbcConnection ;
public JdbcConnection getJdbcConnection () {
return jdbcConnection ;
}
public void setJdbcConnection (JdbcConnection jdbcConnection ) {
this .jdbcConnection = jdbcConnection ;
}
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/SpringIn5StepsBasicApplication.java
package com .in28minutes .spring .basics .springin5steps ;
import org .springframework .context .annotation .AnnotationConfigApplicationContext ;
import org .springframework .context .annotation .ComponentScan ;
import org .springframework .context .annotation .Configuration ;
import com .in28minutes .spring .basics .springin5steps .basic .BinarySearchImpl ;
@ Configuration
@ ComponentScan
public class SpringIn5StepsBasicApplication {
public static void main (String [] args ) {
try (AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext (
SpringIn5StepsBasicApplication .class )) {
BinarySearchImpl binarySearch =
applicationContext .getBean (BinarySearchImpl .class );
BinarySearchImpl binarySearch1 =
applicationContext .getBean (BinarySearchImpl .class );
System .out .println (binarySearch );
System .out .println (binarySearch1 );
int result = binarySearch .binarySearch (new int [] { 12 , 4 , 6 }, 3 );
System .out .println (result );
}
}
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/SpringIn5StepsCdiApplication.java
package com .in28minutes .spring .basics .springin5steps ;
import org .slf4j .Logger ;
import org .slf4j .LoggerFactory ;
import org .springframework .context .annotation .AnnotationConfigApplicationContext ;
import org .springframework .context .annotation .ComponentScan ;
import org .springframework .context .annotation .Configuration ;
import com .in28minutes .spring .basics .springin5steps .cdi .SomeCdiBusiness ;
@ Configuration
@ ComponentScan
public class SpringIn5StepsCdiApplication {
private static Logger LOGGER = LoggerFactory .getLogger (SpringIn5StepsCdiApplication .class );
public static void main (String [] args ) {
try (AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext (
SpringIn5StepsCdiApplication .class )) {
SomeCdiBusiness business = applicationContext .getBean (SomeCdiBusiness .class );
LOGGER .info ("{} dao-{}" , business , business .getSomeCDIDAO ());
}
}
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/SpringIn5StepsComponentScanApplication.java
package com .in28minutes .spring .basics .springin5steps ;
import org .slf4j .Logger ;
import org .slf4j .LoggerFactory ;
import org .springframework .context .annotation .AnnotationConfigApplicationContext ;
import org .springframework .context .annotation .ComponentScan ;
import org .springframework .context .annotation .Configuration ;
import com .in28minutes .spring .basics .componentscan .ComponentDAO ;
@ Configuration
@ ComponentScan ("com.in28minutes.spring.basics.componentscan" )
public class SpringIn5StepsComponentScanApplication {
private static Logger LOGGER = LoggerFactory .getLogger (SpringIn5StepsComponentScanApplication .class );
public static void main (String [] args ) {
try (AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext (
SpringIn5StepsComponentScanApplication .class )) {
ComponentDAO componentDAO = applicationContext .getBean (ComponentDAO .class );
LOGGER .info ("{}" , componentDAO );
}
}
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/SpringIn5StepsPropertiesApplication.java
package com .in28minutes .spring .basics .springin5steps ;
import org .springframework .context .annotation .AnnotationConfigApplicationContext ;
import org .springframework .context .annotation .ComponentScan ;
import org .springframework .context .annotation .Configuration ;
import org .springframework .context .annotation .PropertySource ;
import com .in28minutes .spring .basics .springin5steps .properties .SomeExternalService ;
@ Configuration
@ ComponentScan
//
@ PropertySource ("classpath:app.properties" )
public class SpringIn5StepsPropertiesApplication {
public static void main (String [] args ) {
try (AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext (
SpringIn5StepsPropertiesApplication .class )) {
SomeExternalService service = applicationContext .getBean (SomeExternalService .class );
System .out .println (service .returnServiceURL ());
}
}
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/SpringIn5StepsScopeApplication.java
package com .in28minutes .spring .basics .springin5steps ;
import org .slf4j .Logger ;
import org .slf4j .LoggerFactory ;
import org .springframework .context .annotation .AnnotationConfigApplicationContext ;
import org .springframework .context .annotation .ComponentScan ;
import org .springframework .context .annotation .Configuration ;
import com .in28minutes .spring .basics .springin5steps .scope .PersonDAO ;
@ Configuration
@ ComponentScan
public class SpringIn5StepsScopeApplication {
private static Logger LOGGER = LoggerFactory .getLogger (SpringIn5StepsScopeApplication .class );
public static void main (String [] args ) {
try (AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext (
SpringIn5StepsScopeApplication .class )) {
PersonDAO personDao = applicationContext .getBean (PersonDAO .class );
PersonDAO personDao2 = applicationContext .getBean (PersonDAO .class );
LOGGER .info ("{}" , personDao );
LOGGER .info ("{}" , personDao .getJdbcConnection ());
LOGGER .info ("{}" , personDao .getJdbcConnection ());
LOGGER .info ("{}" , personDao2 );
LOGGER .info ("{}" , personDao .getJdbcConnection ());
}
}
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/SpringIn5StepsXMLContextApplication.java
package com .in28minutes .spring .basics .springin5steps ;
import org .slf4j .Logger ;
import org .slf4j .LoggerFactory ;
import org .springframework .context .support .ClassPathXmlApplicationContext ;
import com .in28minutes .spring .basics .springin5steps .xml .XmlPersonDAO ;
public class SpringIn5StepsXMLContextApplication {
private static Logger LOGGER = LoggerFactory .getLogger (SpringIn5StepsScopeApplication .class );
public static void main (String [] args ) {
try (ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext (
"applicationContext.xml" )) {
LOGGER .info ("Beans Loaded -> {}" , (Object ) applicationContext .getBeanDefinitionNames ());
// [xmlJdbcConnection, xmlPersonDAO]
XmlPersonDAO personDao = applicationContext .getBean (XmlPersonDAO .class );
LOGGER .info ("{} {}" , personDao , personDao .getXmlJdbcConnection ());
}
}
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/xml/XmlJdbcConnection.java
package com .in28minutes .spring .basics .springin5steps .xml ;
public class XmlJdbcConnection {
public XmlJdbcConnection () {
System .out .println ("JDBC Connection" );
}
}
/src/main/java/com/in28minutes/spring/basics/springin5steps/xml/XmlPersonDAO.java
package com .in28minutes .spring .basics .springin5steps .xml ;
public class XmlPersonDAO {
XmlJdbcConnection xmlJdbcConnection ;
public XmlJdbcConnection getXmlJdbcConnection () {
return xmlJdbcConnection ;
}
public void setXmlJdbcConnection (XmlJdbcConnection jdbcConnection ) {
this .xmlJdbcConnection = jdbcConnection ;
}
}
/src/main/resources/app.properties
external.service.url =http://someserver.dev.com/service
/src/main/resources/application.properties
# logging.level.org.springframework = debug
/src/main/resources/applicationContext.xml
<?xml version =" 1.0" encoding =" UTF-8" ?>
<beans xmlns =" http://www.springframework.org/schema/beans"
xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
xmlns : context =" http://www.springframework.org/schema/context"
xsi : schemaLocation =" http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd" >
<context : component-scan base-package =" com.in28minutes.spring.basics" />
<bean id =" xmlJdbcConnection"
class=" com.in28minutes.spring.basics.springin5steps.xml.XmlJdbcConnection" >
</bean >
<bean id =" xmlPersonDAO" class =" com.in28minutes.spring.basics.springin5steps.xml.XmlPersonDAO" >
<property name =" xmlJdbcConnection" ref =" xmlJdbcConnection" />
</bean >
</beans >
/src/main/resources/log.txt
Searching directory [/in28Minutes/git/getting-started-in-5-steps/spring-in-5-steps/target/classes/com/in28minutes/spring/basics/springin5steps] for files matching pattern [/in28Minutes/git/getting-started-in-5-steps/spring-in-5-steps/target/classes/com/in28minutes/spring/basics/springin5steps/**/*.class]
Identified candidate component class: file [/in28Minutes/git/getting-started-in-5-steps/spring-in-5-steps/target/classes/com/in28minutes/spring/basics/springin5steps/BinarySearchImpl.class]
Identified candidate component class: file [/in28Minutes/git/getting-started-in-5-steps/spring-in-5-steps/target/classes/com/in28minutes/spring/basics/springin5steps/BubbleSortAlgorithm.class]
Creating instance of bean 'binarySearchImpl'
Creating instance of bean 'bubbleSortAlgorithm'
Finished creating instance of bean 'bubbleSortAlgorithm'
Constuctor - Autowiring by type from bean name 'binarySearchImpl' via constructor
to bean named 'bubbleSortAlgorithm'
Setter - Autowiring by type from bean name 'binarySearchImpl' to bean named 'bubbleSortAlgorithm'
No Setter or Constructor - Autowiring by type from bean name 'binarySearchImpl' to bean named 'bubbleSortAlgorithm'
Finished creating instance of bean 'binarySearchImpl'
/src/test/java/com/in28minutes/spring/basics/springin5steps/SpringIn5StepsBasicApplicationTests.java
package com .in28minutes .spring .basics .springin5steps ;
import org .junit .Test ;
import org .junit .runner .RunWith ;
import org .springframework .boot .test .context .SpringBootTest ;
import org .springframework .test .context .junit4 .SpringRunner ;
@ RunWith (SpringRunner .class )
@ SpringBootTest
public class SpringIn5StepsBasicApplicationTests {
@ Test
public void contextLoads () {
}
}