DI:Dependency Injection 依赖注入,在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件。
默认情况下,DI会自动调用Bean对象的无参构造器,然后通过对应的set方法注入值,所以一定要保证无参构造器、set方法存在。
当程序调用applicationContext.getBean("id值")的时候,Spring系统会先找到对应的类的无参构造器实例化一个对象,然后再调用其setXxx("")方法注入属性值。
配置文件中借助
package com.au.dao;
public class StudentDao {
public void addStudent() {
System.out.println("dao: addStudent()...");
}
}
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();
}
}
<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="studentDaoId" class="com.au.dao.StudentDao">bean>
<bean id="studentServiceId" class="com.au.service.StudentService">
<property name="studentDao" ref="studentDaoId">property>
bean>
beans>
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();
}
}
- 注意需要写带参构造器。
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 + "]";
}
}
- 按照名字注入:需要
constructor-arg
标签的name
值与类中属性的名称一致。- 按照类型与索引注入:下标从
0
开始,需要声明对应的数据类型。- 如果类中属性不是基本类型,
constructor-arg
标签中用ref
代替value
,与上述set
注入类似。
<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>
<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>
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);
}
}
package DI_test;
public class StudentFactory {
/*
* 非静态方法
*/
public Student getStudent() {
return new Student(1, "hzj");
}
/*
* 静态方法
*/
public static Student getStudent_static() {
return new Student(2, "zhangsan");
}
}
- 对于非静态方法的注入方式,必须实例化工厂类
(factory-bean)
后才能调用工厂方法。
<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>
- 对于静态方法的注入方式,无须创建工厂类实例的情况下就可以调用工厂类方法。
<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>
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);
}
}
- factory-bean:用于实例化工厂类。
- factory-method:用于调用工厂类方法。
自动注入:容器依照一些规则去装配bean中的一个属性。
自动注入有两种形式,byName和byType。
package autowire_test.dao;
public class UserDao {
public void addUser() {
System.out.println("添加成功!");
}
}
添加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();
}
}
byName
注入可以有两个类型一样的bean
,根据类中属性名来匹配bean.xml
的id
值。
<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 id="userDao1" class="autowire_test.dao.UserDao">bean>
<bean id="userService" autowire="byName" class="autowire_test.service.UserService">bean>
beans>
byType
注入不能有两个类型一样的bean
,否则会注入失败。
<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 id="userService" autowire="byName" class="autowire_test.service.UserService">bean>
beans>
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();
}
}
在beans标签中将属性default-autowire="byName"或"byType"即可。
<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>