DI(Dependency Injection):依赖注入,依赖注入实现了控制反转的思想。指Spring创建对象的过程中,将对象依赖属性通过配置进行注入。 依赖指的是对象和对象之间的关联关系。注入指的是一种数据传递行为,通过注入行为来让对象和对象产生关系。
依赖注入常见的实现方式包括两种:set注入和构造注入
①创建学生类Student 该类需要包括无参构造函数,以及每个属性的set方法
public class Student {
private Integer id;
private String name;
private Integer age;
private String sex;
public Student() {
}
public Integer getId() {return id;}
public void setId(Integer id) {this.id = id;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public Integer getAge() { return age;}
public void setAge(Integer age) {this.age = age;}
public String getSex() {return sex;}
public void setSex(String sex) {this.sex = sex;}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + ''' +
", age=" + age +
", sex='" + sex + ''' +
'}';
}
}
复制代码
②配置bean时为属性赋值
复制代码
再次强调一下:
①在Student类中添加有参构造
public Student(Integer id, String name, Integer age, String sex) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
复制代码
②配置bean
spring-di.xml
复制代码
注意:
constructor-arg标签还有两个属性可以进一步描述构造器参数:
index属性:指定参数所在位置的索引(从0开始) name属性:指定参数名 直接根据类型去匹配
了解一些特殊值的处理之前先了解一下spring里认为哪些被称为简单值类型,以下是BeanUtils类的方法,该方法的作用是检查给定类型是否表示“简单”值类型:基本数据类型或基本数据类型的包装器、枚举、字符串或其他字符序列、数字、日期、时态、URI、URL、区域设置或类,并且 void 不被视为简单值类型。:
package org.springframework.beans;
public abstract class BeanUtils {
······
/**
* Check if the given type represents a "simple" value type: a primitive or
* primitive wrapper, an enum, a String or other CharSequence, a Number, a
* Date, a Temporal, a URI, a URL, a Locale, or a Class.
* {@code Void} and {@code void} are not considered simple value types.
* @param type the type to check
* @return whether the given type represents a "simple" value type
* @see #isSimpleProperty(Class)
*/
public static boolean isSimpleValueType(Class<?> type) {
return (Void.class != type && void.class != type &&
(ClassUtils.isPrimitiveOrWrapper(type) ||
Enum.class.isAssignableFrom(type) ||
CharSequence.class.isAssignableFrom(type) ||
Number.class.isAssignableFrom(type) ||
Date.class.isAssignableFrom(type) ||
Temporal.class.isAssignableFrom(type) ||
URI.class == type ||
URL.class == type ||
Locale.class == type ||
Class.class == type));
}
······
}
复制代码
下面再来看一些特殊的值,就是这些特殊的值该怎么注入到属性里面
什么是字面量?
int a = 10;
声明一个变量a,初始化为10,此时a就不代表字母a了,而是作为一个变量的名字。当我们引用a的时候,我们实际上拿到的值是10。
而如果a是带引号的:'a',那么它现在不是一个变量,它就是代表a这个字母本身,这就是字面量。所以字面量没有引申含义,就是我们看到的这个数据本身。
复制代码
注入空字符串使用:
注入null使用:
复制代码
注意:
复制代码 以上写法,name属性是有值的,所赋的值就是字符串‘null’
XML中有5个特殊字符,分别是:<、>、'、"、&
以上5个特殊符号在XML中会被特殊对待,会被当做XML语法的一部分进行解析,如果这些特殊符号直接出现在注入的字符串当中,会报错。举个例子:
复制代码
特殊字符 | 转义字符 |
> | > |
< | < |
' | ' |
" | " |
& | & |
除了使用实体符号来代替,也可以使用CDATA节
复制代码
注意:使用CDATA时,不能使用value属性,只能使用value标签。
Date虽然被Spring认为是简单值类型,使用value赋值,但是value后的字符串不能随便写,格式必须符合Date的toString()方法格式,例如Thu Mar 02 18:06:45 HKT 2023。但是,Date也可以用ref进行赋值,用ref赋值的方式有很多,主要是看用什么样的方式构造出一个Date类型的对象。
复制代码
①创建班级类Clazz
public class Clazz {
private Integer clazzId;
private String clazzName;
public Integer getClazzId() {return clazzId;}
public void setClazzId(Integer clazzId) {this.clazzId = clazzId;}
public String getClazzName() {return clazzName;}
public void setClazzName(String clazzName) {this.clazzName = clazzName;}
@Override
public String toString() {
return "Clazz{" +
"clazzId=" + clazzId +
", clazzName='" + clazzName + ''' +
'}';
}
public Clazz() {}
public Clazz(Integer clazzId, String clazzName) {
this.clazzId = clazzId;
this.clazzName = clazzName;
}
}
复制代码
②修改Student类
在Student类中添加以下代码:
private Clazz clazz;
public Clazz getClazz() {
return clazz;
}
public void setClazz(Clazz clazz) {
this.clazz = clazz;
}
复制代码
配置Clazz类型的bean:
复制代码
为Student中的clazz属性赋值:
复制代码
错误演示:
复制代码
如果错把ref属性写成了value属性,会抛出异常: Caused by: java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'com.qiuye.spring6.bean.Clazz' for property 'clazz': no matching editors or conversion strategy found
意思是不能把String类型转换成我们要的Clazz类型,说明我们使用value属性时,Spring只把这个属性看做一个普通的字符串,不会认为这是一个bean的id,更不会根据它去找到bean来赋值
复制代码
使用级联属性赋值,被注入的类的该属性必须提供get方法,例如把Clazz对象注入到Student对象,Student类必须提供clazz属性的get方法,而且再Bean标签里面必须先给clazz赋值,再给clazz下的属性赋值,顺序不能颠倒。
复制代码
①修改Student类
在Student类中添加hobbies属性,类型是数组:
private String[] hobbies;
public String[] getHobbies() {
return hobbies;
}
public void setHobbies(String[] hobbies) {
this.hobbies = hobbies;
}
复制代码
②配置bean
抽烟
喝酒
烫头
a
复制代码
在Clazz类中添加以下代码:
private List students;
public List getStudents() {
return students;
}
public void setStudents(List students) {
this.students = students;
}
复制代码
配置bean:
复制代码
若为Set集合类型属性赋值,只需要将其中的list标签改为set标签即可,同数组一样注入简单类型用value标签,注入其他类型用ref标签。
创建教师类Teacher:
public class Teacher {
private Integer teacherId;
private String teacherName;
public Integer getTeacherId() {
return teacherId;
}
public void setTeacherId(Integer teacherId) {
this.teacherId = teacherId;
}
public String getTeacherName() {
return teacherName;
}
public void setTeacherName(String teacherName) {
this.teacherName = teacherName;
}
public Teacher(Integer teacherId, String teacherName) {
this.teacherId = teacherId;
this.teacherName = teacherName;
}
public Teacher() {
}
@Override
public String toString() {
return "Teacher{" +
"teacherId=" + teacherId +
", teacherName='" + teacherName + ''' +
'}';
}
}
复制代码
在Student类中添加以下代码:
private Map teacherMap;
public Map getTeacherMap() {
return teacherMap;
}
public void setTeacherMap(Map teacherMap) {
this.teacherMap = teacherMap;
}
复制代码
配置bean:
抽烟
喝酒
烫头
复制代码
要点:
java.util.Properties继承java.util.Hashtable,所以Properties也是一个Map集合。它的key和value都是String类型,使用
com.mysql.cj.jdbc.Driver
jdbc:mysql://localhost:3306/spring
root
123456
复制代码
引入p命名空间 xmlns:p="www.springframework.org/schema/p"
<?xml version="1.0" encoding="UTF-8"?>
复制代码
引入p命名空间后,可以通过以下方式为bean的各个属性赋值,非简单类型需要加ref
复制代码
p命名空间是简化set注入的,所以它基于set方法注入的
C命名空间是为了简化构造注入的配置,使用c命名空间需要引入xmlns:c="www.springframework.org/schema/c",并且需要提供构造方法
复制代码
Util命名空间的作用是允许配置复用,就是一些相同属性可以提取出来,在需用的地方进行引入。 在使用util命名空间之前,需要先引入xmlns:util="http://www.springframework.org/schema/util"和http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd 需要注意引入的内容和地方。
util命名空间主要是针对集合来使用的,具体就需要看场景需求。
<?xml version="1.0" encoding="UTF-8"?>
com.mysql.cj.jdbc.Driver
jdbc:mysql://localhost:3306/spring
root
123456
复制代码
Spring还可以完成自动化的注入,自动化注入又被称为自动装配。它可以根据名字进行自动装配,也可以根据类型进行自动装配。
public class UserService {
private UserDAO userDAO;
private UserMysqlDAO userMysqlDAO;
public void setDao(UserDAO userDAO) {
this.userDAO = userDAO;
}
public void setUserMysqlDAO(UserMysqlDAO userMysqlDAO) {
this.userMysqlDAO = userMysqlDAO;
}
public void add(){
userDAO.add();
userMysqlDAO.add();
}
}
复制代码
复制代码
这个配置起到关键作用:
再来看看根据类型进行自动装配,此时需要使用autowire="byType":
复制代码
同理,byType在装配的时候都是基于set方法的。所以set方法是必须要提供的。提供构造方法是不行的,大家可以测试一下。有一点需要注意,根据类型装配时,如果配置文件中有两个类型一样的bean,会抛出异常,所以使用byType时,必须保证注入的bean类型是唯一的。
我们都知道编写数据源的时候是需要连接数据库的信息的,例如:driver url username password等信息。如果把这些信息单独写到一个属性配置文件中,这样用户修改起来不就会更加的方便嘛。
①在类路径下新建jdbc.properties文件
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/spring
username=root
password=root123
复制代码
②在spring中配置文件里面引入context命名空间
xmlns:context="http://www.springframework.org/schema/context"和http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
③使用context命名空间的标签,使用location来指定文件的位置,用${}来获取对应key的值
<?xml version="1.0" encoding="UTF-8"?>
链接:https://juejin.cn/post/7212812263097368635
页面更新:2024-05-28
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号