一般物件與物件間會有所謂的相依性(dependency),例如教室相依於學生
package com.example;
public class Classroom {
private Student stu=null ;
public Classroom(){
stu=new Student() ;
}
}
但是為了保持物件間的相依關係和物件各自獨立的情況下(保持低耦合Decoupling),則會有所謂的相依性注入(Dependency Injection)
package com.example;
public class Classroom {
private Student stu=null ;
public Classroom(Student stu){
this.stu=stu ;
}
}
Spring 所採用的是DI來實現控制反轉(Inversion of Control;IOC),DI主要意義就是透過抽象介面來注入相依的物件。主要有兩種DI,如下所示:
Constructor-based dependency injection
Classroom.java
package com.example;
public class Classroom {
private Student student=null ;
public Classroom(Student student){
this.student=student ;
}
public void getClean(){
student.clean() ;
}
}
Student.java
package com.example;
public class Student {
public void clean(){
System.out.println("Student clean classroom");
}
}
Main.java
package com.example ;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("Beans.xml");
Classroom classroom = (Classroom) context.getBean("Classroom");
classroom.getClean();
}
}
利用Beans.xml可參照物件中的相依關係
Beans.xml
結果顯示如下所示:
Student clean classroom
setter-based dependency injection
Classroom.java
package com.example;
public class Classroom {
private Student student ;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public void goClean(){
student.clean() ;
}
}
Student.java
package com.example;
public class Student {
public void clean(){
System.out.println("Student clean classroom");
}
}
Main.java
package com.example ;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("Beans.xml");
Classroom classroom = (Classroom) context.getBean("Classroom");
classroom.goClean();
}
}
Beans.xml
結果顯示如下所示:
Student clean classroom
Beans.xml中Bean的constructor-arg也有以下設定方式:
Customer.java
package com.example ;
public class Customer {
private String name ;
private int age ;
public Customer(String name,int age){
this.name=name ;
this.age=age ;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Main.java
package com.example ;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("Beans.xml");
Customer cust = (Customer) context.getBean("Customer");
System.out.println("name:"+cust.getName()) ;
System.out.println("age:"+cust.getAge()) ;
}
}
Beans.xml
Paul 31
另外,也可針對不同變數type去做設定
Customer.java
package com.example ;
public class Customer {
private String name ;
private Integer age ;
public Customer(String name,Integer age){
this.name=name ;
this.age=age ;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Main.java
package com.example ;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("Beans.xml");
Customer cust = (Customer) context.getBean("Customer");
System.out.println("name:"+cust.getName()) ;
System.out.println("age:"+cust.getAge()) ;
}
}
Beans.xml
Paul 31
結果顯示如下所示:
name:Paul
age:31
要使用Constructor-based dependency injection或是Setter-based dependency injection就是取決於物件建立時所有資源都準備好,或是物件建立完後由setter來進行設定。利用setter的方式比較明確知道注入的物件會是什麼,且在記憶上也是較容易記憶的,而constructor則是物件建構完後,一併完成DI的建立。