SpringIoc就是控制反转或者叫依赖注入 :就是创建组件和使用分离。然而这是句废话,面试说了跟没说一样的效果。我们从IOC的基本思想出发,为什么要有IOC的概念。
首先,举个例子,图片从慕课网视频上面copy过来的,只要能弄懂,不择手段。
DI举例,如果要设计一个行李箱的话,最底层为轮子,轮子设计好了之后设计底盘,然后直到设计完成行李箱的过程,那么如果中途XX公司的设计师忽然改了轮子设计,那么地盘、箱体、行李箱全部都得改,基本就报废了,所以这种上层依赖下层的实现是不合理的。代码设计如下:
在未进行控制反正IOC之前,上层类中依赖一个类对象时,一般会自己手动new一个依赖类的对象出来,然后再进行使用。底层一改牵动全身,所以才有了IOC控制反转的概念,就是上层建筑不需要依赖下层,直接让它注入进去就好。例如:设计一个行李箱,那么在设计之前就注入了箱体,箱体之前已经注入了底盘和轮子,直接实例化出行李箱就好。一样先见图,再看代码设计进行比较参考:
有了IOC是控制反转,在不用spring控制反转前,个人的习惯做法是在A类中依赖一个B类对象时,一般会自己手动new一个B类的对象出来,然后再进行使用,有了spring的IOC之后我便可以在配置文件中决定我生成哪个B类对象,然后在需要B类对象的地方只需要注入就可以了。这样降低了A跟B之间的耦合度,有了IOC之后,创建对象的权利由我们手中转移到了spring框架中,更加有利于工作中的协同合作,同时减少了我们的工作量。
IOC容器的优势:
1、避免了各处使用new来创建类,并且可以做到统一维护
2、创建实例的时候不需要了解其中的细节
另外依赖注入的几种方式为:
1、Setter注入。
一 Setter注入Bean
1、创建一个HelloService接口
package com.lanhuigu.spring.common;
public interface HelloService {
void sayHello(String name);
}
2、HelloServiceImpl实现类
package com.lanhuigu.spring.common;
public class HelloServiceImpl implements HelloService{
@Override
public void sayHello(String name) {
System.out.println("hello:" + name);
}
}
3、创建一个SelfIntroductionService(自我介绍)接口
package com.lanhuigu.spring.constructor;
public interface SelfIntroductionService {
void selfIntroduction();
}
4、SelfIntroductionServiceImpl实现类
package com.lanhuigu.spring.setter;
import com.lanhuigu.spring.common.HelloService;
public class SelfIntroductionServiceImpl implements SelfIntroductionService {
private HelloService helloService;
// setter方式注入Bean
public void setHelloService(HelloService helloService) {
this.helloService = helloService;
}
@Override
public void selfIntroduction() {
// 向大家打招呼
helloService.sayHello("大家好!");
}
}
5、Spring XML配置applicationContext-Setter.xml
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
Bean声明:
该bean类似于javaConfig中的@Bean注解;
用于创建bean的类通过class属性来指定,并且需要使用全限定的类名。
通过id指定bean的ID。如果不显示指定,默认使用class的全限定名进行命名。
eg:
com.lanhuigu.spring.common.HelloServiceImpl#0,其#0是一个计数器的形式,
用来区分相同类型的其他bean。
使用自动化命名很方便,但是没有多少实际用处,还是建议自己给bean显示设定ID。
-->
<bean id="helloService" class="com.lanhuigu.spring.common.HelloServiceImpl"/>
<!-- setter注入bean -->
<bean id="selfIntroductionService" class="com.lanhuigu.spring.setter.SelfIntroductionServiceImpl">
<property name="helloService" ref="helloService"/>
</bean>
</beans>
2、Interface注入。现在一般不用该方式
3、Constructor注入。上文代码中已有。
4、Annotation注入,基于Spring注解方式。例如@Autowired
依赖倒置原则、IOC、DI、IOC容器的关系。
1、依赖倒置原则的包含如下的三层含义:
- 高层模块不应该依赖低层模块,两者都应该依赖其抽象
- 抽象不应该依赖细节
- 细节应该依赖抽象
2、有了依赖倒置原则的指导才有IOC的思路,离不开DI的支撑。IOC最重要的就是容器,控制bean的生命周期和bean的注入。