Spring回顾(一)IoC & DI

来源:互联网 发布:淘宝下架宝贝在哪里 编辑:程序博客网 时间:2024/05/16 12:35

什么是IoC?何为DI?

IoC是Sprnig框架实现的一种代替程序员,管理Java类的模式。IoC全称为Inversion of Control,即控制反转。在Spring项目中,将Java类的控制权交给了Spring的IoC容器。类与类之间的泛化关系、依赖关系都能通过Spring的配置来实现,而不需要手动编写。

DI,全称为Dependency Injection,即依赖注入。在Spring通过配置文件配置了依赖关系之后,可以通过多种方式对对象进行注入,比如说Service实现类中的方法需要依赖dao实现类,我们就能通过Spring配置文件写好注入配置,在使用时,我们只需要定义好dao接口,而不需要去获取它的实例,由Spring为我们注入。


能通过Spring的IoC容器和DI做什么?

1. IoC(控制反转)

控制反转,能让spring容器为我们创建对象。简单来说,我们只需要准备好Object object
Spring能帮我们实现余下的new Object()部分。在Spring中,每个被放入容器的类被成为bean,ApplicationContext代表了IoC容器,我们可以通过这个类来读取配置文件,根据配置文件实例化bean。下面看看如何通过配置实现控制反转

1.1 配置文件

配置文件一般放在class目录下,即开发中的src目录。配置文件的主要结构如下:

<?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">    <!--           beans  存放了很多个类          把一个类放入到spring容器中,该类就是bean     -->     <!--           一个bean就是描述一个类          id就是标示符          命名规范:类的第一个字母变成小写,其他的字母保持不变          class为类的全名      -->     <bean id="helloWorld" class="com.spring.ioc.HelloWorld"></bean></beans>

1.2 ApplicationContext 的使用

ApplicationContext在Spring中代表一个IoC容器,ApplicationContext只是一个接口,在这里我用ClassPathXmlApplicationContext这个实现类来直接获取配置文件。其中在容器中对象的创建又有三种方法:根据默认构造方法创建、静态工厂方法创建、实例工厂方法创建

默认构造方法创建

springIoc容器默认情况下会根据bean的构造函数来实例化对象。所以在bean的配置中我们可以添加参数,参数可以是变量也可以是另一个bean的引用,如果是bean的引用,则使用ref=”bean_id”来关联。
配置方式applicationContext.xml

<bean id="helloWorld" class="com.spring.ioc.HelloWorld"></bean>

HelloWorld.java

package com.spring.ioc;public class HelloWorld {    public HelloWorld(){        System.out.println("create a HelloWorld!");    }    public void hello(String name){        System.out.println("Hello," + name);    }}

IoCTest.java

package com.spring.ioc;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class IoCTest {    @Test    public void testIoC(){        //读取配置文件        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        //通过getBean方法得到        HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");        helloWorld.hello("Cindy");    }}
静态工厂方法创建对象

可以在配置bean的时候可以配置使用静态工厂来实例化对象。Spring容器会在内部调用静态工厂的实例化方法来实例化对象。
配置方式:applicationContext.xml

<bean id="helloWorld" class="com.spring.ioc.HelloWorldFactory"           factory-method="getInstance">    </bean>

静态工厂HelloWorldFactory.java

package com.spring.ioc;public class HelloWorldFactory {    public static HelloWorld getInstance(){        return new HelloWorld();    }}
实例工厂创建对象

使用实例工厂方法实例化对象,在定义bean的时候使用factory-bean属性和factory-method属性,来指定实例工厂的实例方法。与静态工厂方法不同,这里是先实例化了一个工厂类,然后调用了实例化工厂方法,而静态工厂方法不实例化工厂类,直接调用其静态实例化方法。
配置方式:applicationContext.xml

<bean id="helloWorldFactory" class="com.spring.ioc.HelloWorldFactory2"></bean><bean id="helloWorld" factory-method="getInstance" factory-bean="helloWorldFactory"></bean>

实例工厂HelloWorldFactory2.java

package com.spring.ioc;public class HelloWorldFactory2 {    public HelloWorldFactory2(){        System.out.println("create a HelloWorldFactory");    }    public HelloWorld getInstance(){        return new HelloWorld();    }}

1.3 什么时候实例化对象?

①加载Spring容器,加载过程中,调用bean的构造函数为bean创建对象。
②将bean的lazy-init属性,设置为true(默认为false),设置延迟加载,spring容器加载时不实例化,在getBean()的时候才实例化。
一般情况下使用第一种方式,因为在启动过程中就能检测出spring配置文件中包含的错误,更加安全。第二种在启动过程中发现不了配置文件错误。如果要加载的bean实在太消耗性能,再考虑使用第二种方法。

1.4 bean的单例模式和多例模式

在配置bean的过程中,可以为其指定是否使用单例模式实例化对象,默认为单例模式,即只实例化一次,多次使用。设置的方法为:
① 多例模式:scope=prototype

<bean id="helloWorld" class="com.spring.ioc.HelloWorld" scope="prototype"></bean>

②单例模式(defalut): scope=singleton

<bean id="helloWorld" class="com.spring.ioc.HelloWorld" scope="singleton"></bean>

1.5 bean的init方法,destory方法

在配置bean的时候,可以为其指定init()方法和destory()方法,分别在实例化和销毁的时候执行。其中在容器关闭时,bean销毁。
配置了之后整个流程可表示为:构造方法(创建对象)->init方法->其他方法->destory方法

*当scope=prototype的时候,spring容器不会执行destory方法

配制方法 applicationContext.xml :

<bean id="helloWorld" class="com.spring.ioc.HelloWorld" init-method="init" destroy-method="destroy"></bean>

HelloWorld.java

package com.spring.ioc;public class HelloWorld {    public HelloWorld(){        System.out.println("create a HelloWorld!");    }    public void hello(String name){        System.out.println("Hello," + name);    }    public void init(){        System.out.println("init HelloWorld");    }    public void destroy(){        System.out.println("destroy HelloWorld");    }}

1.6 bean继承关系

在spring容器中使用parent属性指定父类,实现继承。例子:

package com.spring.xml.extend;public class Animal {    public void walk(){        System.out.println("Animal walking");    }}
package com.spring.xml.extend;public class Dog extends Animal {}

配置:

<bean class="com.spring.xml.extend.Animal" id="animal"></bean><bean class="com.spring.xml.extend.Dog" id="dog" parent="animal"></bean>

2. DI(依赖注入)

2.1 setter方式注入

配置bean的时候,我们可以在配置文件中指定实例化时,要注入的属性值。这些值可以是基本数据类型、引用类型、集合类型、或者Propertie,只要在bean的类定义中提供setter方法就能通过配置注入,配置的方法如下:
applicationContext.xml

<bean id="person" class="com.spring.di.Person">    <!--        property描述的就是bean中的属性          name属性就是描述属性的名称          value就是值   如果是基本属性(String),就用value赋值          ref  如果是引用类型,用ref赋值     -->    <property name="pid" value="1"></property>    <property name="name" value="Cindy"></property>    <!-- 注入bean -->    <property name="student" ref="student"></property>    <property name="lists">        <list>            <value>list1</value>            <value>list2</value>            <!--                list中存放一个student对象             -->            <ref bean="student"/>        </list>    </property>    <property name="objects">        <list>            <value>obj1</value>            <ref bean="student"/>        </list>    </property>    <property name="sets">        <set>            <value>set1</value>            <ref bean="student"/>        </set>    </property>    <property name="map">        <map>            <entry key="m1">                <value>m1</value>            </entry>            <entry key="m2">                <ref bean="student"/>            </entry>        </map>    </property>    <property name="properties">        <props>            <prop key="p1">p1</prop>            <prop key="p2">p2</prop>        </props>    </property></bean><bean id="student" class="com.spring.di.Student"      scope="prototype"></bean>

Student.java

package com.spring.di;public class Student {    public Student(){        System.out.println("student");    }    public void say(){        System.out.println("student");    }}

Person.java

public class Person {    private Long pid;    private String name;    private Student student;    private List lists;    private Set sets;    private Map map;    private Object[] objects;    private Properties properties;    public Person(){        System.out.println("person");    }    //...    //省略setter方法}

2.2 Constructor 注入

除了调用setter方法注入,还能通过类的构造器来注入参数,同样是从配置文件中对bean进行配置。首先在类中定义好构造器方法,然后在配置文件中设置参数。
配置方法:
applicationContext.xml

<bean id="person1" class="com.spring.di.Person1">    <constructor-arg value="Cindy" index="0"></constructor-arg>    <constructor-arg ref="student" index="1"></constructor-arg></bean>

Person1.java

package com.spring.di;public class Person1 {    private String name;    private Student student;    public Person1(String name, Student student) {        this.name = name;        this.student = student;    }}

IoC 和 DI 带来的好处(优势)

让客户端实现完全面向接口编程,在编写客户端的时候,不用关心实现类为什么具体类型,只用接口类型来完成工作,接口需要具体为何种类型的实例,由配置文件决定。举个例子,在一个struts2的aciton中,用接口定义了一个service,而这个service通过spring注入,那么开发action的人员就不需要管service具体是如何实现的,把编写service的工作分离出去,方便团队开发,避免编写过程中的冲突。

Spring是如何实现IoC和DI的

了解Spring框架底层是如何实现控制反转和依赖注入,需要深入研究源码。因为我还没有深入研究过,只知道大概是使用了Java的反射机制,来操作类。有待自己深入研究。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 实体店家纺想换货怎么办 劳动仲裁裁决部分不服怎么办 劳动仲裁公司拒不履行怎么办? 苹果手机被黑客锁了怎么办 出租大面积厂房的中介费用怎么办 中山房子网签不了怎么办 物业服务太差该怎么办 取完公积金的卡怎么办 车卖了对方不过户怎么办 卫生间下水道堵了怎么办妙招 教练不让你练车怎么办 教练不让我练车怎么办 考三要练车教练不给练怎么办 科目二指纹打卡指纹不清楚怎么办 教练凶你的时候怎么办 人行聘用制3年后怎么办 道路运输从业资格证过期了怎么办 码头如果要危险运输证怎么办? 7座车怎么办载客营运证 商调函到了原单位不配合怎么办 公司车辆超证了怎么办? 准迁证过期了5年怎么办 天津中派木业不发工资怎么办 在香港餐厅嫌冷怎么办 出国读研报到证怎么办 高中后出国留学档案怎么办 爱迪花园拆了怎么办 燕郊房子卖了户口怎么办 强制险单子丢了怎么办 车辆保险贴丢了怎么办 车险原单子丢了怎么办 车险保单丢了该怎么办? 审车保险单丢了怎么办 湖州公积金贷款买房具体信用怎么办 驾驶本扣分满了怎么办 摩托车被扣12分怎么办 驾照被扣12分怎么办 骑摩托被扣12分怎么办 摩托车没有驾照违章被扣分怎么办 高考登录密码丢了怎么办 高中档案遗失里面体检表怎么办