什么是IOC
IOC全称是Inversion of Control(控制反转),所谓控制反转是对于程序本身而言,以前我们在创建对象的时候是自己通过new创建出来,而现在我们把这个权力交给了Spring去做,让它帮我们去创建对象和管理对象,对对象的控制权反转给了Spring
什么是DI
DI全称是Dependency Injection(依赖注入),所谓依赖注入是对于Spring的IOC容器而言,以前我们在给对象的属性赋值时有两种渠道,一种是通过带参数的构造方法,另一种是通过set方法。而现在IOC容器在创建对象的同时把属性的值注入进去。
什么是依赖:比如A对象的属性里有B对象,那么就叫A依赖B
Spring的DI实例
依赖注入有两种方式,一种是基于对象的构造函数,另一种是基于对象属性对象的set方法,基本实现思路是这样的:
- 基于构造函数:Spring参考bean配置,提取出bean对象的参数,通过构造方法实例化bean对象
- 基于属性的set方
- 法:Spring参考bean配置,首先先通过无参的构造方法实例化bean对象,然后通过set方法设置bean对象的属性
- 注入基本数据类型(8大基本数据类+String)
/* User.java */
public class User {
private String account;
private String password;
private Float balance;
public User(String account, String password, Float balance) {
this.account = account;
this.password = password;
this.balance = balance;
}
public User(){
System.out.println("User对象创建了");
}
@Override
public String toString() {
return "User{" +
"account='" + account + ''' +
", password='" + password + ''' +
", balance=" + balance +
'}';
}
public String getAccount() {
System.out.println("set方法调用了");
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Float getBalance() {
return balance;
}
public void setBalance(Float balance) {
this.balance = balance;
}
}
/* main函数 */
public class TestMain {
public static void main(String[] args) {
System.out.println(userDao.selectUserByAccount("2018"));
AbstractApplicationContext factory = new ClassPathXmlApplicationContext("ApplicationContext.xml");
User user = (User) factory.getBean("user");
System.out.println(user);
}
}
<!-- 配置文件-->
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.cjh.domain.User">
<property name="account" value="2019"></property>
<property name="password" value="123"></property>
<property name="balance" value="777"></property>
</bean>
</beans>
如果是基本数据类型/String的话,直接通过value写入要传递的值,底层会根据属性的具体类型将value转换成对应的数据类型
注入聚合对象
- 如果是对象里面套了另一个对象,有两种写法,一种是在bean里面配置一个bean,另一种是在bean里面引入一个外部bean
第一种写法
/* person.java */ public class Person { private String name; //引入了上面的user对象 private User user; public Person(){} @Override public String toString() { return "Person{" + "name='" + name + ''' + ", user=" + user + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
//主函数 public class TestMain { public static void main(String[] args) { System.out.println(userDao.selectUserByAccount("2018")); ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); Person person = (Person) context.getBean("person"); System.out.println(person); } }
<!-- 配置文件 --> <?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="person" class="com.cjh.domain.Person"> <property name="name" value="john"></property> <property name="user"> <bean id="user" class="com.cjh.domain.User"> <property name="account" value="2019"></property> <property name="password" value="123"></property> <property name="balance" value="777"></property> </bean> </property> </bean> </beans>
第二种写法
- 通过property标签中的ref属性引入一个外部变量
<!-- 配置文件 -->
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="person" class="com.cjh.domain.Person">
<property name="name" value="john"></property>
<property name="user" ref="user"></property>
</bean>
<bean id="user" class="com.cjh.domain.User">
<property name="account" value="2019"></property>
<property name="password" value="123"></property>
<property name="balance" value="777"></property>
</bean>
</beans>
注入集合
- 注入List、set、map、properties集合
//TestCollection.java
package com.cjh.domain;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class TestCollection {
private List<String> list;
private Set<String> set;
private Map<Integer, String> map;
private Properties properties;
public TestCollection(){}
@Override
public String toString() {
return "TestCollection{" +
"list=" + list +
", set=" + set +
", map=" + map +
", properties=" + properties +
'}';
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Set<String> getSet() {
return set;
}
public void setSet(Set<String> set) {
this.set = set;
}
public Map<Integer, String> getMap() {
return map;
}
public void setMap(Map<Integer, String> map) {
this.map = map;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
}
//主函数
public class TestMain {
public static void main(String[] args) {
System.out.println(userDao.selectUserByAccount("2018"));
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
TestCollection collection = (TestCollection) context.getBean("testCollection");
System.out.println(collection);
}
}
<!-- 配置信息 -->
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="testCollection" class="com.cjh.domain.TestCollection">
<property name="list">
<list value-type="java.lang.String">
<value>12</value>
<value>13</value>
<value>14</value>
<value>15</value>
</list>
</property>
<property name="set">
<set value-type="java.lang.String">
<value>abc</value>
<value>def</value>
<value>ghi</value>
<value>jkl</value>
<value>mno</value>
</set>
</property>
<property name="map">
<map key-type="java.lang.Integer" value-type="java.lang.String">
<entry key="1" value="a"/>
<entry key="2" value="b"/>
<entry key="3" value="c"/>
</map>
</property>
<property name="properties">
<props value-type="String">
<prop key="a">1</prop>
<prop key="b">2</prop>
<prop key="c">3</prop>
</props>
</property>
</bean>
</beans>
- 注入null和空字符串
<bean id="person" class="com.cjh.domain.Person">
<property name="name" value=""></property>
<property name="user">
<null></null> </property></bean>
如上的配置中,value什么都不给就默认为""空串,如果需要注入null,需要使用null标签,如果直接用value="null",Spring会把它解析成字符串null
自动装配
byName:在获取当前bean对象的时候,会根据当前对象的属性名,在配置文件下找到id/name属性与之一样的bean对象,装配给当前bean对象(通过属性的set方法)
- 注意:这里我自己手动试过,当属性名与bean标签的name/id名不一致,但是set方法(set方法的命名规则:set+属性名)的属性名与name/id一致,也是可以装配成功的
- 所以我得出:Spring是根据set方法的后缀属性名字与bean标签中的name/id匹配(个人意见)
byType:在获取当前bean对象的时候,根据当前对象属性的类型,在配置文件下找到相同类型的bean对象,并装配给当前bean对象(通过属性的set方法)
- 如果beans下存在多个相同类型的bean对象,那么会报错
如果当前bean对象的属性类型是接口、抽象类或者普通类的父类,有三种情况
- 当属性对应的set方法的参数也是上述三种类型,如果beans下只有一个与之匹配的可实例化类型(子类/普通类的父类),那么装配成功
- 当属性对应的set方法的参数也是上述三种类型,但是beans下有多个与之匹配的可实例化类型,那么报错
- 当属性对应的set方法的参数是可实例化的类型,并且beans下只有一个与之匹配的类型,装配成功,如果有多个,那么报错
constructor:根据带参的构造方法进行装配
- 根据构造方法的参数名和bean标签的id/name名是否一致
根据构造方法的参数类型和bean标签的class类型是否一致
- 如果构造方法的参数类型是父类,那么beans下要有唯一与之匹配的bean对象(出现多个不装配)
- 以上两点满足其中1点即可装配
- no:不支持自动装配功能
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。