java框架学习日志-2

上篇文章(java框架学习日志-1)虽然跟着写了例子,也理解为何这么写,可是有个疑问,为何叫控制反转?控制的是什么?反转又是什么?
控制其实就是控制对象的建立。
反转与正转对应,正转是由程序自己来建立对象,而反转就是程序自己不建立对象。而是被动地接收对象。
上篇文章虽然把对象的建立这一步移至客户端,可是终究仍是由程序来建立对象的。Spring提供了一个Ioc容器,能够用它来建立对象,在spring中,全部java类都是资源,全部资源都是Bean,管理这些Bean的就是Spring提供的Ioc容器。
若是不使用Ioc容器去生成对象,那么全部对象都要靠程序自己建立,若是测试人员要测试一个类,就要本身去构建这个类,和这个类所依赖的其余类,可是测试人员对构建对象并不熟悉,并且也会加大工做量。
若是不使用Ioc容器会怎么样呢?举个例子,咱们若是要吃饭,那么就要本身煮饭,本身作菜,本身作饮料。这就是主动去建立对象,可是在有了Ioc容器后,Ioc容器就像饭店,咱们只须要描述本身须要什么,而后就不用关注作饭的具体过程,而后等饭端上来就行了,这就是被动地接收对象,下面是代码演示。java

主动建立对象

首先须要一个锅,而后准备米饭,饮料,肉。spring

public class Pan {

    /**
     *锅
     * @param rice 加米饭
     * @param juice 喝什么饮料
     * @param meat 吃什么肉
     * @return 成品
     */
    public String cooking(String rice,String juice,String meat){
        String food=rice+"配"+meat+",再喝点"+juice;
        return food;
    }
}

而后是烹饪过程,须要new一个锅,传入米饭等参数的具体值编程

public class FoodMaker {
    private Pan pan=new Pan();
    private String rice;
    private String juice;
    private String meat;

    public String getRice() {
        return rice;
    }

    public void setRice(String rice) {
        this.rice = rice;
    }

    public String getJuice() {
        return juice;
    }

    public void setJuice(String juice) {
        this.juice = juice;
    }

    public String getMeat() {
        return meat;
    }

    public void setMeat(String meat) {
        this.meat = meat;
    }

    public String makefood(){
        return pan.cooking(rice,juice,meat);
    }
}

最后测试一下设计模式

public class Test {
    public static void main(String[] args) {
        FoodMaker foodMaker=new FoodMaker();
        foodMaker.setRice("白米饭");
        foodMaker.setJuice("可乐");
        foodMaker.setMeat("黄焖鸡");
        String food=foodMaker.makefood();
        System.out.println(food);
    }
}


而后用被动建立对象来实现上面的代码。框架

被动建立对象

在写代码以前须要先导入相关jar包,这个能够去spring官网下载,既然要用bean去管理java类,那么就须要一个bean的xml文件,在src目录下新建xml文件

既然用的别人的东西,那么就须要导入头文件,spring的头文件,模板以下,如今不用管为何这么写,复制就对了,以前提到过,bean就是java对象,由spring容器来建立和管理,这里的name能够换成id。id是惟一的,name是别名。class就是类的全限定名,包括位置,由于我这里没写包,因此就只是类名。property就是类里的参数,value就是参数的值。在教学视频中bean的name和类名都是hello,后面要用到hello的时候我分不清楚传的究竟是哪一个,因此这里我就用了不同的名字。工具

<?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-2.5.xsd">
    <bean name="cooking" class="FoodMaker">
        <property name="rice" value="土豆饭"/>
        <property name="juice" value="红茶"/>
        <property name="meat" value="小炒肉"/>
    </bean>
</beans>

而后就能够测试一下了学习

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        //解析beans.xml文件,生成相应对象,传入bean容器的名字
        ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
        FoodMaker foodMaker=(FoodMaker)context.getBean("cooking");//cooking就是FoodMaker的别名
        System.out.println(foodMaker.makefood());
    }
}

结果。注意结果是经过commons logging打印的,这个须要的jar包一样在spring里面。
测试

从结果上来看,两种写法是同样的,可是经过spring来实现代码,就不须要程序来建立对象,对象是由spring容器建立的,对象的属性是由spring容器来设置的。这么一个过程就叫控制反转。这样的话,若是之后须要添加对象,就不用修改代码,能够直接经过bean容器来管理和建立对象,好比再添加一顿饭就能够这样添加。ui

<?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-2.5.xsd">
    <bean name="cooking" class="FoodMaker">
        <property name="rice" value="土豆饭"/>
        <property name="juice" value="红茶"/>
        <property name="meat" value="小炒肉"/>
    </bean>
    <bean name="cooking2" class="FoodMaker">
        <property name="rice" value="炒饭"/>
        <property name="juice" value="肥仔快乐水"/>
        <property name="meat" value="肥仔快乐堡"/>
    </bean>
</beans>

测试结果

控制反转还有个名字叫依赖注入。在上面的例子中,依赖指的是FoodMaker对rice,juice,meat的依赖。而rice等属性的值是由容器给的,这叫依赖注入,实际上是一个东西,只是看的角度不同。this

总结

其实ioc是一种编程思想,它的目的也是遵循了设计模式中的下降程序耦合度,方便拓展,避免修改。上面例子中是将对象的建立脱离出程序自己,让spring去完成,其实这只是一方面,主要思想是将主动编程变成被动接受。本身去new对象也是主动编程,接收对象也是接收资源。 Ioc的实现是经过ioc容器实现的,ioc容器就是bean工厂(由于bean能够建立不少对象,并且因此也叫bean工厂。bean工厂其实也是工厂模式,只是这种工厂模式是由spring提供,以前看设计模式,觉得这些设计模式都要本身写,原来也有轮子能够用,好比单例模式,只要在beans.xml里的class="FoodMaker"后面加上scope="single"。代码以下

<bean name="cooking" class="FoodMaker" scope="singleton">
        <property name="rice" value="土豆饭"/>
        <property name="juice" value="红茶"/>
        <property name="meat" value="小炒肉"/>
    </bean>

上面的例子其实使用bean来建立对象还不够完全,在FoodMaker类里面,还有个Pan对象是咱们手动建立的。以前在只是简单的给一些String属性赋值,那若是是复杂一点的对象怎么赋值呢?代码以下:
修改在FoodMaker的代码,让pan的值为null,生成set,get方法,经过set,get方法来给pan赋值。

private Pan pan=null;
    private String rice;
    private String juice;
    private String meat;

    public Pan getPan() {
        return pan;
    }

    public void setPan(Pan pan) {
        this.pan = pan;
    }

beans.xml布置文件以下,其中ref是引用对象,由spring建立。之后若是添加其余烹饪工具,只须要用spring建立对象,而后传入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
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    <bean id="pan" class="Pan"/>
    <bean name="cooking" class="FoodMaker">
        <property name="rice" value="土豆饭"/>
        <property name="juice" value="红茶"/>
        <property name="meat" value="小炒肉"/>
        <property name="pan" ref="pan"></property>
    </bean>
</beans>

注意!!!

public class FoodMaker {
    private Pan pan=null;//id=“pan”的pan不是这里的pan。
    private String rice;
    private String juice;
    private String meat;

    public Pan getPan() {
        return pan;
    }

    public void setPan(Pan pan) {//注意在beans文件中,id=“pan”中的pan,其实setPan中的Pan首字母小写。
        this.pan = pan;
    }

若是这里setPan改为setPPP,那么beans文件里相应的id也要改为pPP,因此必定要注意书写规范,我在写这个例子的时候,由于写xml文件时不会实时纠错,而系统给的错误信息又太多看不懂,因此排错排了好久,才发现是大小写错了。最后再测试一下这个代码,运行结果和以前同样,就不贴图了。

相关文章
相关标签/搜索