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=""
// 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使用: 或者不为该属性赋值
// 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