天天看点

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>