JAVA-反射机制(3)-IoC(控制反转)原理

来源:互联网 发布:摄影网络教学 编辑:程序博客网 时间:2024/06/05 22:55

IOC中最基本的技术就是“反射(Reflection)”编程,通俗来讲就是根据给出的类名(字符串方式)来动态地生成对象,这种编程方式可以让对象在生成时才被决定到底是哪一种对象。只是在Spring中要生产的对象都在配置文件中给出定义,目的就是提高灵活性和可维护性。
目前C#、Java和PHP5等语言均支持反射,其中PHP5的技术书籍中,有时候也被翻译成“映射”。有关反射的概念和用法,大家应该都很清楚。反射的应用是很广泛的,很多的成熟的框架,比如像Java中的hibernate、Spring框架,.Net中NHibernate、Spring.NET框架都是把”反射“做为最基本的技术手段。
反射技术其实很早就出现了,但一直被忽略,没有被进一步的利用。当时的反射编程方式相对于正常的对象生成方式要慢至少得10倍。现在的反射技术经过改良优化,已经非常成熟,反射方式生成对象和通常对象生成方式,速度已经相差不大了,大约为1-2倍的差距。
我们可以把IOC容器的工作模式看做是工厂模式的升华,可以把IOC容器看作是一个工厂,这个工厂里要生产的对象都在配置文件中给出定义,然后利用编程语言提供的反射机制,根据配置文件中给出的类名生成相应的对象。从实现来看,IOC是把以前在工厂方法里写死的对象生成代码,改变为由配置文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。
Spring Ioc(Inverse of Control) 控制反转,通过注入来实现实例创建,而不是通过new来指定对象。
Spring中的IoC的实现原理就是工厂模式加反射机制。

1.我们首先看一下不用反射机制时的工厂模式

/** * 工厂模式 */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();    }}

当我们在添加一个子类的时候,就需要修改工厂类了。如果我们添加太多的子类的时候,改的就会很多。

2. 利用反射机制的工厂模式

package Reflect;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();        }    }}

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

3.使用反射机制并结合属性文件的工厂模式(即IoC)
首先创建一个fruit.properties的资源文件:
apple=Reflect.Apple
orange=Reflect.Orange
然后编写主类代码:

package Reflect;import java.io.*;import java.util.*;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