天天看點

Spring DI(依賴注入)的幾種方法Spring DI(依賴注入)的幾種方法

Spring DI(依賴注入)的幾種方法

文章目錄

  • Spring DI(依賴注入)的幾種方法
    • DI概念
    • 一、 set方法注入
      • a. 建立StudentDao.java類
      • b. 建立StudentService.java類
      • c. 建立bean.xml檔案
      • d. 建立測試類
    • 二、 構造器注入
      • a. 建立Student.java類
      • b. 建立bean.xml檔案
        • 1. 按照名字注入
        • 2. 按照類型與索引注入
      • c. 建立測試類
    • 三、 工廠注入
      • a. 建立工廠類
      • b. 配置bean.xml檔案
        • 1. 普通工廠
        • 2. 靜态工廠
      • c. 建立測試類
      • d. 總結
    • 四、 自動注入
      • a. 建立UserDao.java類
      • b. 建立UserService.java類
      • c. 建立bean.xml檔案
        • 1. byName注入
        • 2. byType注入
      • d. 建立測試類
    • 五、 所有bean設定自動注入

DI概念

DI:Dependency Injection 依賴注入,在Spring架構負責建立Bean對象時,動态的将依賴對象注入到Bean元件。

一、 set方法注入

預設情況下,DI會自動調用Bean對象的無參構造器,然後通過對應的set方法注入值,是以一定要保證無參構造器、set方法存在。

當程式調用applicationContext.getBean("id值")的時候,Spring系統會先找到對應的類的無參構造器執行個體化一個對象,然後再調用其setXxx("")方法注入屬性值。

配置檔案中借助<property name="屬性名" ref="id"></property>實作set注入,如果該屬性是基本類型或者對應的包裝類型,可将ref更換為value,然後直接寫值,比如<property name="age" value="20"></property>。

a. 建立StudentDao.java類

package com.au.dao;

public class StudentDao {
	public void addStudent() {
		System.out.println("dao: addStudent()...");
	}
}
           

b. 建立StudentService.java類

package com.au.service;

import com.au.dao.StudentDao;

public class StudentService {
	// 需要set注入,建立setStudentDao方法
	StudentDao studentDao;

	public void setStudentDao(StudentDao studentDao) {
		this.studentDao = studentDao;
	}

	public void addStudent() {
		studentDao.addStudent();
	}
}
           

c. 建立bean.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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- bean配置 -->
	<bean id="studentDaoId" class="com.au.dao.StudentDao"></bean>

    <!-- 裡面用property标簽來實作set注入 -->
	<bean id="studentServiceId" class="com.au.service.StudentService">
		<property name="studentDao" ref="studentDaoId"></property>
	</bean>

</beans>
           

d. 建立測試類

package com.au.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.au.service.StudentService;

public class Main {

	@Test
	public void test01() {
		// Spring IOC,不用自己new對象,通過Spring來實作調用addStudent方法,底層使用了工廠模式+反射
		String xmlPath = "com/au/test/bean.xml";
		ApplicationContext ac = new ClassPathXmlApplicationContext(xmlPath);
		StudentService service = (StudentService) ac.getBean("studentServiceId");
        // 可以發現,并沒有new StudentDao對象,一樣可以調用addStudent()方法,說明注入成功
		service.addStudent();
	}

}
           

二、 構造器注入

a. 建立Student.java類

  • 注意需要寫帶參構造器。
package DI_test;

public class Student {
	private Integer id;
	private String name;

	public Student() {
	}

	public Student(Integer id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + "]";
	}

}
           

b. 建立bean.xml檔案

  • 按照名字注入:需要

    constructor-arg

    标簽的

    name

    值與類中屬性的名稱一緻。
  • 按照類型與索引注入:下标從 開始,需要聲明對應的資料類型。
  • 如果類中屬性不是基本類型,

    constructor-arg

    标簽中用

    ref

    代替

    value

    ,與上述

    set

    注入類似。

1. 按照名字注入

<?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.xsd">


	<bean id="studentId" class="DI_test.Student">
		<constructor-arg name="id" value="10"></constructor-arg>
		<constructor-arg name="name" value="張三"></constructor-arg>
	</bean>

</beans>
           

2. 按照類型與索引注入

<?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.xsd">

	<bean id="studentId" class="DI_test.Student">
		<constructor-arg index="0" type="Integer" value="10"></constructor-arg>
		<constructor-arg index="1" type="String" value="張三"></constructor-arg>
	</bean>

</beans>
           

c. 建立測試類

package DI_test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	@Test
	public void test01() {
		String xmlPath = "DI_test/bean.xml";
		ApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
		Student student = (Student)context.getBean("studentId");
		System.out.println(student);
	}
}
           

三、 工廠注入

a. 建立工廠類

package DI_test;

public class StudentFactory {
	/*
	 * 非靜态方法
	 */
	public Student getStudent() {
		return new Student(1, "hzj");
	}

	/*
	 * 靜态方法
	 */
	public static Student getStudent_static() {
		return new Student(2, "zhangsan");
	}
}
           

b. 配置bean.xml檔案

1. 普通工廠

  • 對于非靜态方法的注入方式,必須執行個體化工廠類

    (factory-bean)

    後才能調用工廠方法。
<?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.xsd">

	<bean id="factory" class="DI_test.StudentFactory"></bean>
	
	<bean id="getStudent" factory-bean="factory" factory-method="getStudent"></bean>
</beans>
           

2. 靜态工廠

  • 對于靜态方法的注入方式,無須建立工廠類執行個體的情況下就可以調用工廠類方法。
<?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.xsd">
	
	<bean id="getStudent" class="DI_test.StudentFactory" factory-method="getStudent_static"></bean>
	
</beans>
           

c. 建立測試類

package DI_test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	/*
	 * 測試靜态工廠
	 */
	@Test
	public void test02() {
		String xmlPath = "DI_test/bean.xml";
		ApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
		Student student = (Student) context.getBean("getStudent");
		System.out.println(student);
	}
	/*
	 * 測試普通工廠
	 */
	@Test
	public void test03() {
		String xmlPath = "DI_test/bean.xml";
		ApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
		Student student = (Student) context.getBean("getStudent");
		System.out.println(student);
	}
}
           

d. 總結

  • factory-bean:用于執行個體化工廠類。
  • factory-method:用于調用工廠類方法。

四、 自動注入

自動注入:容器依照一些規則去裝配bean中的一個屬性。

自動注入有兩種形式,byName和byType。

a. 建立UserDao.java類

package autowire_test.dao;

public class UserDao {
	public void addUser() {
		System.out.println("添加成功!");
	}
}
           

b. 建立UserService.java類

添加UserDao userDao為屬性,并添加setUserDao方法。

package autowire_test.service;

import autowire_test.dao.UserDao;

public class UserService {

	UserDao userDao;

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	public void addUser() {
		userDao.addUser();
	}

}
           

c. 建立bean.xml檔案

1. byName注入

  • byName

    注入可以有兩個類型一樣的

    bean

    ,根據類中屬性名來比對

    bean.xml

    id

    值。
<?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.xsd">

    <!-- 因為屬性名叫userDao,是以會注入這個 -->
	<bean id="userDao" class="autowire_test.dao.UserDao"></bean>
	
    <!-- 因為屬性名叫userDao,是以不會注入這個 -->
	<bean id="userDao1" class="autowire_test.dao.UserDao"></bean>
	
	<bean id="userService" autowire="byName" class="autowire_test.service.UserService"></bean>

</beans>
           

2. byType注入

  • byType

    注入不能有兩個類型一樣的

    bean

    ,否則會注入失敗。
<?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.xsd">

	<bean id="userDao" class="autowire_test.dao.UserDao"></bean>
	
    <!-- 不能有兩個一樣類型的bean -->
	<!-- <bean id="userDao1" class="autowire_test.dao.UserDao"></bean> -->
	
	<bean id="userService" autowire="byName" class="autowire_test.service.UserService"></bean>

</beans>
           

d. 建立測試類

package autowire_test.main;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import autowire_test.service.UserService;

public class Main {
	@Test
	public void test01() {
		String xmlPath = "autowire_test/main/bean.xml";
		ApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
		UserService userService = (UserService) context.getBean("userService");
		userService.addUser();
	}
}
           

五、 所有bean設定自動注入

在beans标簽中将屬性default-autowire="byName"或"byType"即可。

<?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.xsd" 
                           default-autowire="byType">
                            <!-- ^ 這設定 -->
</beans>