Spring
Inversion Of Control (IOC)
If class A depend on class B , pass the declaration of class B to third party to declare
Example: If a graduate want to find a suitable job , he should find the agent to help him to look for his suitable job according to his abilities, instead of every student find for the same job.
Dependency injection is a one of the example of inversion of control
Without IOC
public class Graduate {
private Programmer programmer;
}
// That assume all the graduate must find a programmer job, which is strongly coupled
With IOC
public class Graduate{
private Job job;
public void setJob(Job job){
this.job = job;
}
}
// The job class is an interface;
// The job of the graduate will handled by another class(e.g Main class)
// which make the graduate loosely coupled with Job class
Dependency Injection
Initial
public class Lesson{
private Student student;
public Lesson(){
this.student = new Student();
}
}
Dependency Injection (by constructor)
public class Lesson{
private Student student;
public Lesson(Student exampleStudent){
this.student = exampleStudent;
}
}
Dependency Injection (by setter)
public class Lesson{
private Student student;
public void setStudent(student exampleStudent){
this.student = new Student();
}
}
Initially, lesson class is fixed with a specific student class. If we declare new Lesson class, the student must be the same as every lesson class, which will cause out coupling.
By using dependency injection, lesson class and student will be independent to each other.
Why Spring?
It has strong IOC container (Application Context) which manage and create the beans
Developer can do dependency injection easily by using the bean of container
Structure of Java Spring
Data Access Integration
Provide several popular API , such as hibernate, JPA
Make the syntax of connecting database simpler
Web
Provide several web function, such as file reader
Define Controller, Model and View
Core
Application Context Container or Bean Factory Container is a container to contain the bean factory which is a xml file traditionally
Application Context Container
package com.yiibai;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class MainApp {
public static void main(String[] args) {
XmlBeanFactory factory = new XmlBeanFactory
(new ClassPathResource("Beans.xml"));
HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");
obj.getMessage();
}
}
Bean Factory Container
package com.yiibai;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class MainApp {
public static void main(String[] args) {
XmlBeanFactory factory = new XmlBeanFactory
(new ClassPathResource("Beans.xml"));
HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");
obj.getMessage();
}
}
Bean
Introduction
Bean can be instantiated as a instance of the class, which is similar with the below syntax to declare the new instance - sample Student
Student sampleStudent = new Student("Chan Tai Man", 12);
Bean can rely on another beans by using auto wire
Example of creating bean by using traditional xml
// HelloWorld.java
package com.yiibai;
public class HelloWorld {
private String message;
public void setMessage(String message){
this.message = message;
}
public void getMessage(){
System.out.println("Your Message : " + message);
}
}
// MainApp.java
package com.yiibai;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="helloWorld" class="com.yiibai.HelloWorld">
<property name="message" value="Hello World!"/>
</bean>
</beans>
// Your Message : Hello World!
Scope
Type
There are 5 types of scope - singleton, prototype, request, session and global session
Singleton: This scopes the bean definition to a single instance per Spring IoC container (default)
Prototype: This scopes a single bean definition to have any number of object instances.
Request: This scopes a bean definition to an HTTP request. Only valid in the context of a web-aware Spring Application Context.
Session: This scopes a bean definition to an HTTP session. Only valid in the context of a web-aware Spring Application Context.
Global-session: This scopes a bean definition to a global HTTP session. Only valid in the context of a web-aware Spring Application Context.
Singleton vs Prototype
// Main.java
package com.yiibai;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld objA = (HelloWorld) context.getBean("helloWorld");
objA.setMessage("I'm object A");
objA.getMessage();
HelloWorld objB = (HelloWorld) context.getBean("helloWorld");
objB.getMessage();
}
}
Singleton
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="helloWorld" class="com.yiibai.HelloWorld"
scope="singleton">
</bean>
</beans>
Output
Your Message : I'm object A
Your Message : I'm object A
Prototype
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="helloWorld" class="com.yiibai.HelloWorld"
scope="prototype">
</bean>
</beans>
Output
Your Message : I'm object A
Your Message : null
Life Cycle
Initialize and Destroy
we can add custom event for each as a listener
// HelloWorld.java
package com.yiibai;
public class HelloWorld {
private String message;
public void setMessage(String message){
this.message = message;
}
public void getMessage(){
System.out.println("Your Message : " + message);
}
public void init(){
System.out.println("Bean is going through init.");
}
public void destroy(){
System.out.println("Bean will destroy now.");
}
}
// Main.java
package com.yiibai;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
AbstractApplicationContext context =
new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
context.registerShutdownHook();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="helloWorld"
class="com.yiibai.HelloWorld"
init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"/>
</bean>
</beans>
Output:
Bean is going through init.
Your Message : Hello World!
Bean will destroy now.
Dependency Injection
By constructor
package x.y;
public class Foo {
public Foo(Bar bar, Baz baz) {
// ...
}
}
<beans>
<bean id="foo" class="x.y.Foo">
<constructor-arg ref="bar"/>
<constructor-arg ref="baz"/>
</bean>
<bean id="bar" class="x.y.Bar"/>
<bean id="baz" class="x.y.Baz"/>
</beans>
By setter
package com.yiibai;
public class TextEditor {
private SpellChecker spellChecker;
// a setter method to inject the dependency.
public void setSpellChecker(SpellChecker spellChecker) {
System.out.println("Inside setSpellChecker." );
this.spellChecker = spellChecker;
}
// a getter method to return spellChecker
public SpellChecker getSpellChecker() {
return spellChecker;
}
public void spellCheck() {
spellChecker.checkSpelling();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<? Method 1 ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- Definition for textEditor bean -->
<bean id="textEditor" class="com.yiibai.TextEditor">
<property name="spellChecker" ref="spellChecker"/>
</bean>
<!-- Definition for spellChecker bean -->
<bean id="spellChecker" class="com.yiibai.SpellChecker">
</bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<? Method 2 ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- Definition for textEditor bean using inner bean -->
<bean id="textEditor" class="com.yiibai.TextEditor">
<property name="spellChecker">
<bean id="spellChecker" class="com.yiibai.SpellChecker"/>
</property>
</bean>
</beans>
Auto Wire
By Type / By Name (XML)
package com.yiibai;
public class TextEditor {
private SpellChecker spellChecker;
private String name;
public void setSpellChecker( SpellChecker spellChecker ){
this.spellChecker = spellChecker;
}
public SpellChecker getSpellChecker() {
return spellChecker;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void spellCheck() {
spellChecker.checkSpelling();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- Definition for textEditor bean -->
<bean id="textEditor" class="com.yiibai.TextEditor"
autowire="byType">
<property name="name" value="Generic Text Editor" />
</bean>
<!-- Definition for spellChecker bean -->
<bean id="spellChecker" class="com.yiibai.SpellChecker">
</bean>
</beans>
In text editor, it will look for the bean containing spell checker type or the same name automatically and inject into text editor
By Type (Annotation)
package com.yiibai;
import org.springframework.beans.factory.annotation.Autowired;
public class TextEditor {
private SpellChecker spellChecker;
@Autowired
public void setSpellChecker( SpellChecker spellChecker ){
this.spellChecker = spellChecker;
}
public SpellChecker getSpellChecker( ) {
return spellChecker;
}
public void spellCheck() {
spellChecker.checkSpelling();
}
}
In text editor, it will look for the bean containing spell checker type automatically and inject into text editor
If spellchecker is a interface , make sure that it should be implemented by one class only
By Name (Annotation)
If a spell checker may be a interface and implement by several class, so we should look for the bean according to the name of the bean
package com.yiibai;
import org.springframework.beans.factory.annotation.Autowired;
public class TextEditor {
private SpellChecker spellChecker;
@Resource(name = "sampleSpellerChecker")
public void setSpellChecker( SpellChecker spellChecker ){
this.spellChecker = spellChecker;
}
public SpellChecker getSpellChecker( ) {
return spellChecker;
}
public void spellCheck() {
spellChecker.checkSpelling();
}
}
Configuration
In spring, we can make good use of annotation instead of configure xml file
Annotation
package com.yiibai;
import org.springframework.context.annotation.*;
@Configuration
public class HelloWorldConfig {
@Bean
public HelloWorld helloWorld(){
return new HelloWorld();
}
}
XML
<beans>
<bean id="helloWorld" class="com.yiibai.HelloWorld" />
</beans>
Component Scanning
Introduction
Initially, we need to declare each bean one by one. Now, we can make good use of annotation to mark the class as a component, and perform scanning on spring container which can be in xml or java code , that will register the bean automatically for class who is marked as a component
@Configuration
@ComponentScan("com.luv2code")
@PropertySource("classpath:sport.properties")
public class SportConfig {
@Bean
public FortuneService normalFortuneService(){
return new NormalFortuneService();
}
@Bean
public Coach swimCoach(){
return new SwimCoach(normalFortuneService());
}
}
There are common 5 annotations to create beans
Component
It can be used in different layers
Not recommended to use
@Component
public class UserComponentImpl implements IUser {
private String name = "UserComponentImpl";
public String get() {
return name;
}
}
@Component(value="componentBeanId")
public class UserComponentImplWithParam implements IUser {
private String name = "UserComponentImplWithParam";
public String get() {
return name;
}
}
@SpringBootApplication
public class ComponentApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(ComponentApplication.class, args);
IUser userComponentImpl1 = (UserComponentImpl)context.getBean("userComponentImpl");
System.out.println(userComponentImpl1.get());
IUser userComponentImpl2 = (UserComponentImplWithParam)context.getBean("componentBeanId");
System.out.println(userComponentImpl2.get());
}
}
// Output:
// UserComponentImpl
// UserComponentImplWithParam
Service
It is one part of the component
Mainly responsible for the business logic
In the most situation, it should be a interface and implemented by different class
public interface TestService {
public void test();
}
@Service
@Scope("singleton")
public class TestServiceImpl implements TestService {
@Override
public void test(){
...
}
}
Repository
It is one part of the component
Mainly responsible for visiting database and locate in the dao folder
@Repository
public interface LocationRepository extends JpaRepository<Location,Integer> {
List<Location> findByName(String name);
}
Controller
It is one part of the component
used to handle URL and can used to return jsp file
Example 1 (Return jsp File)
@Controller
@RequestMapping("/test/{id}")
public class PathVariableTest {
@RequestMapping("/{name}/get.do")
public String get (@PathVariable("id") Integer index, Model model) {
model.addAttribute("id", index);
return "/index";
}
}
Example 2 (return string or other type)
@Controller
@GetMapping("/bi")
public class ResponseBodyTest {
@RequestMapping("/login")
@ResponseBody
public String get () {
return "Hello Spring Boot!";
}
}
RestController
It is one part of the controller
act as a api end point and must be return in string or other type
RestController = Controller + ResponseBody
@RestController
@RequestMapping("/bi")
public class ResponseBodyTest {
@GetMapping("/login")
public String get () {
return "Hello Spring Boot!";
}
}
Last updated
Was this helpful?