Spring框架學習02——Spring IOC 詳解

一、Spring IOC的基本概念

IOC(Inverse of Control)反轉控制的概念,就是將本來在程序中手動建立對象的控制權,交由Spring框架管理。當某個Java對象(調用者)須要調用另外一個Java對象(被調用者)時,在傳統編程模式下,調用者一般會採用「new 被調用者」的代碼方式來建立對象。這種方式會增長調用者與被調用者之間的耦合性,不利於後期代碼的升級與維護。
當Spring框架出現後,對象的實例再也不由調用者來建立,而是由Spring容器來建立。Spring容器會負責控制程序之間的關係,而不是由調用者的程序代碼直接控制。這樣,控制權由調用者轉移到Spring容器,控制權發生了反轉,這就是Spring的控制反轉。java

二、Spring IOC容器

實現控制反轉的是Spring IOC容器,Spring IOC容器的設計主要是基於Bean Factory和ApplicationContext兩個接口。web

2.一、BeanFactory接口

BeanFactory由org.springframework.beans.factory.BeanFactory接口定義,它提供了完整的IOC服務支持,是一個管理Bean的工廠,主要負責初始化各類Bean。
BeanFactory接口最經常使用的實現類是org.springframework.beans.factory.xml.XMLBeanFactory,該類會根據XML配置文件中的定義來裝配Bean。
BeanFactory實例建立代碼以下:spring

@Test
public void demo(){
    FileSystemResource file = new FileSystemResource("C:\\demo\\applicationContext.xml");
    BeanFactory beanFactory = new XmlBeanFactory(file);
    TestDao testDao = (TestDao) beanFactory.getBean("testDao");
    testDao.sayHello();
}

 

因爲使用BeanFactory實例加載Spring配置文件在實際開發中並很少見,因此對於該接口僅瞭解便可。express

2.二、ApplicationContext接口

ApplicationContext是BeanFactory的子接口,也稱爲應用上下文,由org.springframework.context.ApplicationContext接口定義。ApplicationContext接口除了包含BeanFactory的全部功能之外,還添加了對國際化、資源訪問、事件傳播等內容的支持。
建立ApplicationContext接口實例一般有如下3中方法:編程

  • 經過ClassPathXmlApplicationContext建立
  • 經過FileSystemXmlApplicationContext建立
  • 經過Web服務器實例化ApplicationContext容器

下面對這3種方法的代碼作演示:服務器

(1)ClassPathXmlApplicationContextapp

使用ClassPathXmlApplicationContext將從類路徑目錄(src根目錄)中尋找指定的XML配置文件,代碼示例:框架

@Test
public void demo(){
    //初始化Spring容器ApplicationContext,加載配置文件
    ApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml");
    //經過容器獲取testDao實例
    TestDao testDao = (TestDao) application.getBean("testDao");
    testDao.sayHello();

}

(2)FileSystemXmlApplicationContextide

使用FileSystemXmlApplicationContext將從指定文件的絕對路徑中尋找XML配置文件,找到並裝載完成ApplicationContext的實例化工做,代碼示例:測試

@Test
public void demo(){
    ApplicationContext application = new FileSystemXmlApplicationContext("C:\\demo\\applicationContext.xml");
    TestDao testDao = (TestDao) application.getBean("testDao");
    testDao.sayHello();

}

 

(3)使用Web服務器實例化

經過Web服務器實例化ApplicationContext容器,通常使用org.springframework.web.context.ContextLoaderListener的實現方式,須要添加Spring-web依賴,pom.xml配置以下:

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-web</artifactId>
   <version>5.0.2.RELEASE</version>
 </dependency>

在web.xml中配置代碼以下:

<context-param>
  <!--加載src目錄下的applicationContext.xml文件-->
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--指定以ContextLoaderListener方式啓動Spring容器-->
<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

 

經過web.xml配置,web容器會自動加載context-param中的配置文件初始化ApplicationContext實例,而後就能夠在web應用中經過WebApplicationContextUtils.getWebApplicationContext方法獲取ApplicationContext的引用,Servlet中的代碼以下:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws javax.servlet.ServletException, IOException {
    ApplicationContext application = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
    TestDao testDao = (TestDao) application.getBean("testDao");
    testDao.sayHello();
}

三、依賴注入(基於XML方式)

DI (Dependency Injection)依賴注入的概念,在Spring中實現IOC容器的方法是依賴注入,依賴注入的做用是在使用Spring框架建立對象時動態地將其所依賴的對象(屬性值)注入Bean組件中。
Spring框架的依賴注入一般有如下幾種實現方式:

  • 使用構造方法注入
  • 使用屬性的setter方法注入
  • 使用使用P名稱空間注入
  • 使用SpEL注入

3.一、使用構造方法注入

建立User類

package test;

public class User {
    private String name;
    private int age;

    public User(String name,int age){
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

在applicationContext.xml文件中配置user實例

<?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 id="user" class="test.User">
        <constructor-arg name="name" value="張三"></constructor-arg>
        <constructor-arg name="age" value="20"></constructor-arg>
    </bean>
</beans>

在測試方法中代碼

@Test
public void demo(){
    //初始化Spring容器ApplicationContext,加載配置文件
    ApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml");
    //經過容器獲取實例
    User user = (User) application.getBean("user");
    System.out.println(user);
}

運行結果

3.二、使用屬性的setter方法注入

建立Course課程類

package entity;

public class Course {
    private String cname;

    public String getCname() {
        return cname;
    }
    public void setCname(String cname) {
        this.cname = cname;
    }
    @Override
    public String toString() {
        return "Course{" +
                "cname='" + cname + '\'' +
                '}';
    }
}

建立Student學生類

package entity;

public class Student {
    private String name;
    private int age;
    private Course course;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", course=" + course +
                '}';
    }

    //getter和setter方法
}

配置applicationContext.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">

    <!--使用set方法注入-->
    <bean id="course" class="entity.Course">
        <property name="cname" value="大學語文"></property>
    </bean>
    <bean id="student" class="entity.Student">
        <property name="name" value="張三"></property>
        <property name="age" value="20"></property>
        <property name="course" ref="course"></property>
    </bean>
</beans>

測試方法

@Test
public void demo(){
    //初始化Spring容器ApplicationContext,加載配置文件
    ApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml");
    //經過容器獲取實例
    Student student = (Student) application.getBean("student");
    System.out.println(student);

}

運行結果

3.三、使用P名稱空間注入

建立Course課程類

package entity;

public class Course {
    private String cname;

    public String getCname() {
        return cname;
    }
    public void setCname(String cname) {
        this.cname = cname;
    }
    @Override
    public String toString() {
        return "Course{" +
                "cname='" + cname + '\'' +
                '}';
    }
}

建立Student學生類

package entity;

public class Student {
    private String name;
    private int age;
    private Course course;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", course=" + course +
                '}';
    }

    //getter和setter方法
}

配置applicationContext.xml文件,要在約束裏面加入p名稱空間的約束

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       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">

    <!--使用p名稱空間注入-->
    <bean id="course" class="entity.Course" p:cname="英語"></bean>
    <bean id="student" class="entity.Student" p:name="張三" p:age="20" p:course-ref="course"></bean>

</beans>

測試方法

@Test
public void demo(){
    //初始化Spring容器ApplicationContext,加載配置文件
    ApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml");
    //經過容器獲取實例
    Student student = (Student) application.getBean("student");
    System.out.println(student);

}

運行結果

3.四、使用SpEL注入

咱們可使用SpEL(Spring expression language)Spring表達式語言,對依賴注入進行簡化。

語法:#{表達式},例如 <bean id="" value="#{表達式}">

  #{'hello'}:使用字符串

  #{beanId}:使用另外一個bean

  #{beanId.content.toUpperCase()}:使用指定名屬性,並使用方法

  #{T(java.lang.Math).PI}:使用靜態字段或方法

建立Course課程類

package entity;

public class Course {
    private String cname;

    public String getCname() {
        return cname;
    }
    public void setCname(String cname) {
        this.cname = cname;
    }
    @Override
    public String toString() {
        return "Course{" +
                "cname='" + cname + '\'' +
                '}';
    }
}

建立Student學生類

package entity;

public class Student {
    private String name;
    private int age;
    private Course course;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", course=" + course +
                '}';
    }

    //getter和setter方法
}

配置applicationContext.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">

    <!--使用SpEL方式注入-->
    <bean id="course" class="entity.Course">
        <property name="cname" value="#{'高數'}"></property>
    </bean>
    <bean id="student" class="entity.Student">
        <property name="name" value="#{'小明'}"></property>
        <property name="age" value="#{10}"></property>
        <property name="course" value="#{course}"></property>
    </bean>

</beans>

測試方法

@Test
public void demo(){
    //初始化Spring容器ApplicationContext,加載配置文件
    ApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml");
    //經過容器獲取實例
    Student student = (Student) application.getBean("student");
    System.out.println(student);

}

運行結果

在使用SpEL時,配置中也能夠調用方法,示例代碼以下:
建立獲取年齡的類

package entity;

public class GetAge {
    public int createAge(){
        return 20;
    }
}

 

配置applicationContext.xml

<!--使用SpEL方式注入-->
<bean id="course" class="entity.Course">
    <property name="cname" value="#{'高數'}"></property>
</bean>
<bean id="getAge" class="entity.GetAge"></bean>
<bean id="student" class="entity.Student">
    <property name="name" value="#{'小明'}"></property>
    <property name="age" value="#{getAge.createAge()}"></property>
    <property name="course" value="#{course}"></property>
</bean>

執行測試方法,運行結果以下:

相關文章
相關標籤/搜索