- 一、对IOC和DI的基本认识
- (一)理解IoC,即“控制反转”
- (二)IoC能做什么?
- (三)DI又是什么?
- (四)IoC和DI由什么关系呢?
- 二、IOC创建对象的方式
- (一)通过无参构造方法来创建
- (二)通过有参构造方法来创建
- (三)Spring的配置
- 三、依赖注入
- (一)构造器注入
- (二)Set方式注入
- (三)其他扩展方式注入
一、对IOC和DI的基本认识 (一)理解IoC,即“控制反转”
在开发中,Ioc意味着将你设计好的对象交给容器控制,而不是你在你的对象内部直接控制。 要想理解“控制反转”这个词的意思,就要知道,谁控制谁,控制了什么?为什么是反转,哪些地方反转?
- 谁控制了谁,控制了什么?
- 在传统的Java开发中,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建以及外部资源获取。
- 为什么是反转,哪些地方反转?
- 传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象;而反转则是由容器来帮忙创建及注入依赖对象:由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转,依赖对象的获取被反转了。
没有IoC的情况
有了IoC之后的情况
IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则, 它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是 松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。
IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。
DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。 通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
同样的,理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”
- 谁依赖谁?
- 当然是应用程序依赖于IoC容器
- 为什么需要依赖?
- 应用程序需要IoC容器来提供对象需要的外部资源
- 谁注入谁?
- 很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象
- 注入了什么?
- 就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)
其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以它有个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。
二、IOC创建对象的方式 (一)通过无参构造方法来创建- User.java
public class User {
private String name;
public User(){
System.out.println("无参构造创建对象!!!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("name="+name);
}
}
- beans.xml
-->
- 测试类
public class MyTest {
public static void main(String[] args) {
//Spring容器,
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
user.show();
}
}
(二)通过有参构造方法来创建
- User.java
public class User {
private String name;
public User(String name){ //有参构造
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("name="+name);
}
}
2.beans.xml
- 测试类
public class MyTest {
public static void main(String[] args) {
//Spring容器,
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user" );
user.show();
}
}
(三)Spring的配置
- 可以使用import来导入不同的配置文件,比如在applicationContext.xml中
- 别名
- bean的配置
三、依赖注入 (一)构造器注入
此方法上文已经介绍过了
(二)Set方式注入
- 依赖注入:Set注入
- 依赖:bean对象的创建依赖于容器
- 注入:bean对象中的所有属性,由容器来注入
- Address.java和Student.java
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Address{" +
"address='" + address + ''' +
'}';
}
}
public class Student {
private String name;
private Address address;
private String[] books;
private List hobbies;
private Map card;
private Set games;
private Properties info;
private String wife;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String[] getBooks() {
return books;
}
public void setBooks(String[] books) {
this.books = books;
}
public List getHobbies() {
return hobbies;
}
public void setHobbies(List hobbies) {
this.hobbies = hobbies;
}
public Map getCard() {
return card;
}
public void setCard(Map card) {
this.card = card;
}
public Set getGames() {
return games;
}
public void setGames(Set games) {
this.games = games;
}
public Properties getInfo() {
return info;
}
public void setInfo(Properties info) {
this.info = info;
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + ''' +
", address=" + address+
", books=" + Arrays.toString(books) +
", hobbies=" + hobbies +
", card=" + card +
", games=" + games +
", info=" + info +
", wife='" + wife + ''' +
'}';
}
}
- beans.xml
- 测试类
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.getName());
}
}
- beans.xml信息补充
(三)其他扩展方式注入红楼梦 水浒传 西游记 三国演义
唱 跳 rap 篮球 LOL CSGO BF5 1910292 男性 xiaomi
此处的其他扩展方式只介绍p命名空间注入二号c命名空间注入
- userbeans.xml
- 测试类
@Test
public void test2() {
ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
User user = (User) context.getBean("user2");
System.out.println(user);
}
- 补充:p命名空间和c命名空间不能直接使用,需要导入xml约束!
xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"



