1. 依赖注入:
1.1 set注入:
基于set方法实现的, 底层会通过反射机制调用属性对应的set方法然后给属性赋值
这种方式要求属性必须对外提供set方法
set注入的核心实现原理: 通过反射机制调用set方法来给属性赋值, 让俩个对象之间产生关系
// xml
<!-- 配置userDao -->
<bean id="userDaoBean" class="com.powernode.bean.UserDao"/>
<!-- 配置vipDao -->
<bean id="vipDaoBean" class="com.powernode.bean.VipDao"/>
<!-- 配置User -->
<bean id="userBean" class="com.powernode.bean.User">
<!-- 想让Spring调用对应的set方法, 需要配置property标签
name属性怎么知道值: set方法的方法名, 去掉set, 然后把剩下的首字母小写
ref翻译为引用, ref后面指定的是要注入的bean的id -->
<property name="userDao" ref="userDaoBean"/>
<property name="vipDao" ref="vipDaoBean"/>
</bean>
// User类
public class User {
private UserDao userDao;
private VipDao vipDao;
public void setVipDao(VipDao vipDao) {
this.vipDao = vipDao;
}
// set注入, 必须提供一个set方法
// Spring容器会调用这个set方法, 来给userDao属性赋值
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void saveUser(){
userDao.saveId();
vipDao.save();
}
}
// @Test
public void setDI(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
User userBean = ctx.getBean("userBean", User.class);
userBean.saveUser();
}
1.2 构造注入:
核心原理: 调用构造方法来给属性赋值
set注入是在对象构建好了之后调用set方法来完成赋值, 构造注入是在对象实例化的过程中赋值的
// xml
<bean id="userDaoBean" class="com.powernode.bean.UserDao"/>
<bean id="vipDaoBean" class="com.powernode.bean.VipDao"/>
<!-- 构造注入3种方式 -->
<bean id="customerBean" class="com.powernode.bean.Customer">
<!-- 指定构造方法的第一个参数, 下标是0 -->
<constructor-arg index="0" ref="userDaoBean"/>
<!-- 指定构造方法的第二个参数, 下标是1 -->
<constructor-arg index="1" ref="vipDaoBean"/>
<!-- 根据构造方法参数的名字进行注入 -->
<constructor-arg name="userDao" ref="userDaoBean"/>
<constructor-arg name="vipDao" ref="vipDaoBean"/>
<!-- 这种方式实际上是根据类型进行注入, Spring会自动根据类型来判断把ref注入给哪个参数-->
<constructor-arg ref="userDaoBean"/>
<constructor-arg ref="vipDaoBean"/>
</bean>
// Customer类
public class Customer {
private UserDao userDao;
private VipDao vipDao;
public Customer(UserDao userDao, VipDao vipDao) {
this.userDao = userDao;
this.vipDao = vipDao;
}
public void insert(){
userDao.saveId();
vipDao.save();
}
}
// @Test
public void constructorDI(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
Customer customerBean = ctx.getBean("customerBean", Customer.class);
customerBean.insert();
}
2. set注入专题:
2.1 注入外部Bean:
// xml
<bean id="orderDaoBean" class="com.powernode.bean.dao.OrderDao"/>
<bean id="orderBean" class="com.powernode.bean.Order">
// 使用ref属性来引入, 这就是注入外部bean
<property name="orderDao" ref="orderDaoBean"/>
</bean>
// Order类
public class Order {
private OrderDao orderDao;
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
public void generate(){
orderDao.insert();
}
}
2.2 注入内部Bean:
// xml
<bean id="orderBean2" class="com.powernode.bean.Order">
<property name="orderDao">
<!-- 在property标签中使用嵌套的bean标签, 这就是内部bean -->
<bean class="com.powernode.bean.dao.OrderDao"/>
</property>
</bean>
// Order类
public class Order {
private OrderDao orderDao;
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
public void generate(){
orderDao.insert();
}
}
2.3 注入简单类型:
简单类型有哪些:
8 种基本类型和8种包装类型
枚举
String字符串
数字
日期(java.util.Date), 在实际的开发中, 一般不会把Date当做简单类型, 一般采用ref给Date类型的属性赋值
时间时区类型
URI
URL
语言类
Class类型
// xml
<bean id="peopleBean" class="com.powernode.bean.People">
// 如果是给简单类型赋值, 就不能使用ref, 需要使用value
<property name="name" value="二狗"/>
<property name="age" value="16"/>
<property name="classId" value="1"/>
</bean>
// People类
public class People {
private String name;
private int age;
private int classId;
public void setName(String name) {this.name = name;}
public void setAge(int age) {this.age = age;}
public void setClassId(int classId) {this.classId = classId;}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
", classId=" + classId +
'}';
}
}
// @Test
public void setDI3(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("set-DI.xml");
People peopleBean = ctx.getBean("peopleBean", People.class);
System.out.println(peopleBean);
}
2.4 注入数组:
基本类型和非基本类型的数组注入, 如下:
// xml
<bean id="friend1" class="com.powernode.bean.Friend">
<property name="name" value="小北"/>
</bean>
<bean id="friend2" class="com.powernode.bean.Friend">
<property name="name" value="小爱"/>
</bean>
<bean id="friend3" class="com.powernode.bean.Friend">
<property name="name" value="小花"/>
</bean>
<bean id="stu" class="com.powernode.bean.Student">
// 这个数组当中的元素类型是String简单类型
<property name="stus">
<array>
<value>"张三"</value>
<value>"李四"</value>
<value>"王二蛋"</value>
<value>"大锤"</value>
</array>
</property>
// 这个数组当中的类型就不是简单类型
<property name="friends">
<array>
<ref bean="friend1"/>
<ref bean="friend2"/>
<ref bean="friend3"/>
</array>
</property>
</bean>
// Student类
public class Student {
private String[] stus;
private Friend[] friends;
public void setStus(String[] stus) {this.stus = stus;}
public void setFriends(Friend[] friends) {this.friends = friends;}
@Override
public String toString() {
return "Student{" +
"stus=" + Arrays.toString(stus) +
", friends=" + Arrays.toString(friends) +
'}';
}
}
// Friend类
public class Friend {
private String name;
public void setName(String name) {this.name = name;}
@Override
public String toString() {
return "Friend{" +
"name='" + name + '\'' +
'}';
}
}
// @Test
public void setDI5(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("set-DI.xml");
Student stu = ctx.getBean("stu", Student.class);
System.out.println(stu);
}
2.5 注入List集合和Set集合:
简单类型
// xml
<bean id="people" class="com.powernode.bean.People">
<property name="names">
<list> // list集合有序可重复
<value>张三</value>
<value>达尔</value>
<value>溜达</value>
<value>张三</value>
<value>张三</value>
</list>
</property>
<property name="addrs">
<set> // set集合无序不可重复
<value>张二</value>
<value>达</value>
<value>溜达</value>
</set>
</property>
</bean>
// People类
public class People {
private List<String> names;
private Set<String> addrs;
public void setNames(List<String> names) {this.names = names;}
public void setAddrs(Set<String> addrs) {this.addrs = addrs;}
@Override
public String toString() {
return "People{" +
", names=" + names +
", addrs=" + addrs +
'}';
}
}
// @Test
public void setDI5(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("set-DI.xml");
People people = ctx.getBean("people", People.class);
System.out.println(people);
}
2.6 注入Map集合和properties:
Properties本质上也是一个Map集合
Properties的父类HashTable, HashTable实现了Map接口
虽然这个也是Map集合, 但是和Map的注入方式不完全一样
Properties的key和value只能是String类型
// xml
<bean id="people" class="com.powernode.bean.People">
<property name="phones"> // 注入map集合
<map>
<entry key-ref="" value-ref=""/> // 如果key和value不是简单类型就用这个
<entry key="1" value=".."/>
<entry key="2" value=".."/>
<entry key="3" value=".."/>
</map>
</property>
<property name="properties"> // 注入properties属性类对象
<props>
<prop key="..">...</prop>
<prop key="..">...</prop>
<prop key="..">...</prop>
</props>
</property>
</bean>
// People类
public class People {
private Map<Integer,String> phones;
private Properties properties;
public void setPhones(Map<Integer, String> phones) {this.phones = phones;}
public void setProperties(Properties properties) {this.properties = properties;}
@Override
public String toString() {
return "People{" +
"phones=" + phones +
", properties=" + properties +
'}';
}
}
// @Test
public void setDI5(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("set-DI.xml");
People people = ctx.getBean("people", People.class);
System.out.println(people);
}
2.7 注入null和空字符串:
注入空字符串使用: <value/> 或者value=""
// xml
<bean id="dog" class="com.powernode.bean.Dog">
// 注入空字符串的第一种方式
<property name="name">
<value/>
</property>
// 注入空字符串的第二种方式
<property name="age" value=""/>
</bean>
// Dog类
public class Dog {
private String name;
private int age;
public void setName(String name) {this.name = name;}
public void setAge(int age) {this.age = age;}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
// @Test
public void setEmpty(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("set-DI.xml");
Dog dog = ctx.getBean("dog", Dog.class);
System.out.println(dog);
}
注入null使用: <null/> 或者不为该属性赋值
// xml
<bean id="dog" class="com.powernode.bean.Dog">
// 不给属性注入, 属性的默认值就是null
// <property name="name" value=""/>
// 手动注入null
<property name="age">
<null/>
</property>
</bean>
2.8 注入特殊字符:
// xml
<bean id="math" class="com.powernode.bean.Dog">
// 第一种方案
<property name="result" value="2 < 3"/>
// 第二种方案
<property name="result">
// 只能使用value标签
<value><![CDATA[2 < 3]]></value>
</property>
</bean>
3. 引入外部的属性配置文件:
引入外部的properties文件
第一步: 引入context命名空间
第二步: 使用标签context: property-placeholder的location属性来指定属性配置文件的路径
location默认从类的根路径下开始加载资源
// xml
<context: property-placeholder location="jdbc.properties"/>
// 配置数据源
<bean id="ds" class="com....jdbc.MyDataSource">
// 怎么取值呢? ${key}
<property name="driver" value="${jdbc.driverClass}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
// jdbc.properties
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring6
jdbc.username=root
jdbc.password=123