面试必备-如何回答你是怎么理解spring IOC的?

一、 什么是SpringIOC?

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

举个简单的例子帮助理解一下

你想吃一份红烧牛肉面:

普通的做法:就是你去附近找一个饭馆,然后再去这个饭馆点一个这个面。

Ioc的做法:你在手机上外卖平台搜索这个面,然后支付完成后,对应的饭馆会通过送餐员直接送到你面前。

二、 SpringIOC的优点?

1. 解耦

究竟什么是解耦呢?就是降低程序的耦合度,更方便的实现扩展。

其实好多同学还是有点懵的,说的多了反倒越想越迷,解耦其实可以用一句话来概括,就是通过中间者来取消调用者和被调用者的直接关系

比如你想租房子,你需要去网上搜租房信息,有合适的去看,如果不满意,还要去找另一家去看,解耦的话,你只需要把你的需求给房产中介,他就会很方便的帮你带你挑选适合你的房子。

2. 提高系统可插入、可测试、可修改等特性

因为文件可以通过xml或者注解统一进行配置,减少了很多不必要的代码,所以测试和修改就变得更加的简单。

三、 SpringIOC的缺点

1.因为反射的存在,导致性能降低,不过这点损耗不会太影响系统的运行。

2. 缺少IDE重构操作的支持,如果在Eclipse要对类改名,那么你还需要去XML文件里手工去改了,这似乎是所有XML方式的缺憾所在。

四、 SpringIOC的底层原理

1. 反射

1) 反射的概念

反射是Java语言的一个特性,它允许程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个Java类获取它所有的成员变量和方法并且显示出来。

2) 反射机制的作用

1、在运行时判断任意一个对象所属的类。

2、在运行时获取类的对象。

3、在运行时访问java对象的属性,方法,构造方法等。

2.

反射与工厂模式实现IOC

Spring中的IoC的实现原理就是工厂模式加反射机制。 我们首先看一下不用反射机制时的工厂模式:

interface fruit{ 
public abstract void eat();
}
class Apple implements fruit{
public void eat(){
System.out.println("Apple");
}
}
class Orange implements fruit{
public void eat(){
System.out.println("Orange");
}
}
class Factory{
public static fruit getInstance(String fruitName){
fruit f=null;
if("Apple".equals(fruitName)){
f=new Apple();
}
if("Orange".equals(fruitName)){
f=new Orange();
}
return f;
}
}
class hello{
public static void main(String[] a){
fruit f=Factory.getInstance("Orange");
f.eat();
}
}

上面写法的缺点是当我们再添加一个子类的时候,就需要修改工厂类了。如果我们添加太多的子类的时候,改动就会很多。下面用反射机制实现工厂模式:

interface fruit{

public abstract void eat();

}

class Apple implements fruit{

public void eat(){

System.out.println("Apple");

}

}

class Orange implements fruit{

public void eat(){

System.out.println("Orange");

}

}

class Factory{

public static fruit getInstance(String ClassName){

fruit f=null;

try{

f=(fruit)Class.forName(ClassName).newInstance();

}catch (Exception e) {

e.printStackTrace();

}

return f;

}

}

class hello{

public static void main(String[] a){

fruit f=Factory.getInstance("Reflect.Apple");

if(f!=null){

f.eat();

}

}

}

现在就算我们添加任意多个子类的时候,工厂类都不需要修改。使用反射机制实现的工厂模式可以通过反射取得接口的实例,但是需要传入完整的包和类名。而且用户也无法知道一个接口有多少个可以使用的子类,所以我们通过属性文件的形式配置所需要的子类。

下面编写使用反射机制并结合属性文件的工厂模式(即IoC)。首先创建一个fruit.properties的资源文件:

apple=Reflect.Appleorange=Reflect.Orange

然后编写主类代码:

interface fruit{

public abstract void eat();

}

class Apple implements fruit{

public void eat(){

System.out.println("Apple");

}

}

class Orange implements fruit{

public void eat(){

System.out.println("Orange");

}

}

//操作属性文件类

class init{

public static Properties getPro() throws FileNotFoundException, IOException{

Properties pro=new Properties();

File f=new File("fruit.properties");

if(f.exists()){

pro.load(new FileInputStream(f));

}else{

pro.setProperty("apple", "Reflect.Apple");

pro.setProperty("orange", "Reflect.Orange");

pro.store(new FileOutputStream(f), "FRUIT CLASS");

}

return pro;

}

}

class Factory{

public static fruit getInstance(String ClassName){

fruit f=null;

try{

f=(fruit)Class.forName(ClassName).newInstance();

}catch (Exception e) {

e.printStackTrace();

}

return f;

}

}

class hello{

public static void main(String[] a) throws FileNotFoundException, IOException{

Properties pro=init.getPro();

fruit f=Factory.getInstance(pro.getProperty("apple"));

if(f!=null){

f.eat();

}

}

}

运行结果:Apple

五、 SpringIOC三种注入方式

1.接口注入:

接口注入模式因为具备侵入性,它要求组件必须与特定的接口相关联,因此并不被看好,实际使用有限。

2.Setter 注入:

对于习惯了传统 javabean 开发的程序员,通过 setter 方法设定依赖关系更加直观。

如果依赖关系较为复杂,那么构造子注入模式的构造函数也会相当庞大,而此时设值注入模式则更为简洁。

如果用到了第三方类库,可能要求我们的组件提供一个默认的构造函数,此时构造子注入模式也不适用。

3。构造器注入:

在构造期间完成一个完整的、合法的对象。

所有依赖关系在构造函数中集中呈现。

依赖关系在构造时由容器一次性设定,组件被创建之后一直处于相对“不变”的稳定状态。

只有组件的创建者关心其内部依赖关系,对调用者而言,该依赖关系处于“黑盒”之中。

面试必备-如何回答你是怎么理解spring IOC的?

-------END-------

本文参考了许多大牛的精华,如果觉的还不错的话,可以支持一下。


分享到:


相關文章: