Spring(一)—— Spring IOC

Spring簡介

Spring是一個輕量級、開源的框架,核心功能如下:

  • IOC:控制反轉,對象額創建不是通過 new 的形式,而是交給Spring配置創建對象;
  • AOP:面向切面編程,擴展功能而不用修改代碼;(通常用於日誌監控、登陸操作等);

IOC是典型的工廠模式,通過工廠去注入對象,AOP則是代理模式的體現。

Spring提供了一站式的框架,Java EE三層結構中,每一層Spring都提供瞭解決方案:

  1. Controller(Web服務層):Spring MVC;
  2. Service(業務處理層):Spring IOC、AOP;
  3. Dao:Mybatis、jdbcTemplated、Mybatis-Spring整合;

Spring IOC

IOC即控制反轉,把對象的創建交給了Spring管理,IOC的使用有兩種方式:

  1. 通過配置文件;
  2. 通過註解;

IOC的底層原理:

  1. XML配置文件;
  2. dom4j解析XML配置文件,得到需要創建對象的全路徑名;
  3. 利用工廠設計模式,通過反射產生對象;

對象的創建過程:
在這裏插入圖片描述

  1. 創建XML配置文件,配置要創建的對象的類;
示例  <bean id="student" class="com.tulun.bean.Student1"/>
  1. 創建工廠類,利用dom4j解析配置文件,通過反射創建對象;
//大概原理
public class UserFactory {
    public static User getBean() {
        //利用dom4j解析配置文件,通過id屬性值來獲取到類的全路徑名
        String path = "com.tulun.bean.Student1";
        //通過反射創建對象
        Class c = Class.forName(path);
        //創建對象
        User user = (User) c.newInstance();
        return user;
    }
}

IOC的使用(基於配置)

使用步驟:

  1. 引入依賴;
  2. 創建類,在類中添加方法;
  3. 創建Spring的XML配置文件,配置需要創建對象的類;
  4. 使用;

需要引入的Spring的基本依賴包:

        <!--Spring 基本核心jar包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>4.1.7.RELEASE</version>
        </dependency>

Spring創建對象的方式

Spring通過配置文件創建對象的方式(即bean實例化的方式)主要有三種:

  1. 通過無參構造;
  2. 通過靜態工廠創建;
  3. 通過一般工廠創建;

代碼示例:

這三種方式需要創建的對象都是Student1的對象:

public class Student1 {
    public void show() {
        System.out.println("Student1.show()...");
    }
}

一、通過無參構造

配置文件 bean1.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-3.0.xsd">

     <!--創建Student對象
         id和class屬性必填
         id屬性:起名稱,名稱可以隨便給
         class屬性:要讓Spring管理的類的全路徑名

         //這也是實例化bean的第一種方式:通過無參構造(必須要有無參構造,否則會拋出異常)
     -->
    <bean id="student" class="com.tulun.bean.Student1"/>

</beans>

測試:

public class TestDemo1 {
    public static void main(String[] args) {
        //加載Spring配置文件,創建對象
        ApplicationContext context = new ClassPathXmlApplicationContext("bean實例化/bean1.xml");
        Student1 student = (Student1) context.getBean("student");  //參數是id
        student.show();
    }
}

在這裏插入圖片描述
二、使用靜態工廠創建

添加靜態工廠類:

public class StaticFactory {
    public static Student1 getBean() {
        return new Student1();
    }
}

配置文件需要這樣寫,bean2.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-3.0.xsd">

    <!--實例化bean的第2種方式-->

    <!--通過靜態工廠創建Student類-->
    <bean id="student1" class="com.tulun.factory.StaticFactory" factory-method="getBean"></bean>

</beans>

測試:

public class TestDemo2 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean實例化/bean2.xml");
        Student1 student = (Student1)context.getBean("student1");
        student.show();
    }
}

在這裏插入圖片描述

三、通過一般工廠創建:

添加一般工廠類:

public class Factory {
    public Student1 getBean() {
        return new Student1();
    }
}

這個方法實例化bean的時候,我們需要先得到工廠類對象,所以這個時候的配置文件bean3.xml是:

<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-3.0.xsd">

    <!--實例化bean的第三種方式 通過一般工廠-->

    <!--1、先創建工廠對象-->
    <bean id="factory" class="com.tulun.factory.Factory"/>

    <!--2、用工廠來創建bean實例對象-->
    <bean id="student1" factory-bean="factory" factory-method="getBean"/>
</beans>

測試:

public class TestDemo3 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean實例化/bean3.xml");
        Student1 student = (Student1)context.getBean("student1");
        student.show();
    }
}

在這裏插入圖片描述

Spring依賴注入的方式

以上是Spring創建對象的方式,現在來說說Spring如何給屬性賦值,也就是依賴注入(DI);

Java中給屬性賦值的方式有主要三種:

  • 通過有參構造函數;
  • 通過set方法;
  • 通過接口;

在Spring裏面我們主要使用的給屬性賦值的方式有兩種:

  • 有參構造;
  • set方法;

代碼示例:

依賴注入主要是給Student2對象進行屬性注入:

public class Student2 {
    private String name;

    //通過set方法個屬性賦值的時候,先創建的是一個無參的對象
    public Student2() {}

    public Student2(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void show() {
        System.out.println("Student2.show()...");
    }
}

一、通過有參構造

配置文件nature1.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-3.0.xsd">

    <!--通過有參數構造進行屬性注入-->
    <bean id="student" class="com.tulun.bean.Student2">
        <constructor-arg name="name" value="張三"></constructor-arg>
    </bean>

</beans>

測試:

public class TestDemo1 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("屬性的注入/nature1.xml");
        Student2 student = (Student2)context.getBean("student");
        System.out.println(student.getName());
        student.show();
    }
}

在這裏插入圖片描述
二、通過set方法:

這個被創建對象的類一定要有set方法,不然報錯;

nature2.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-3.0.xsd">

    <!--通過set方法進行屬性注入-->
    <bean id="student" class="com.tulun.bean.Student2">
        <property name="name" value="李四"></property>
    </bean>
    
</beans>

測試:

public class TestDemo2 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("屬性的注入/nature2.xml");
        Student2 student = (Student2)context.getBean("student");
        System.out.println(student.getName());
        student.show();
    }
}

在這裏插入圖片描述
複雜屬性的依賴注入

上述我們是對簡單數據類型的屬性進行依賴注入,那麼接下來就是複雜屬性的依賴注入,複雜屬性包括對象、數組、map、List、Properties(配置文件);

先來說說對象的注入:

先創建一個dao層的類:

public class User {
    public void add() {
        System.out.println("User.dao()");
    }
}

再來一個Service層的對象:

public class UserService {
    private User user;

    //需要添加set方法纔可以給屬性賦值
    public void setUser(User user) {
        this.user = user;
    }

    public void add(){
        user.add();
    }
}

現在來寫配置文件nature3.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-3.0.xsd">

    <!--對象屬性注入-->
    <!--創建dao層對象-->
    <bean id="userDao" class="com.tulun.dao.User"></bean>

    <!--創建Service層對象-->
    <bean id="userService" class="com.tulun.service.UserService">
        <!--在service需要使用dao層對象-->
        <property name="user" ref="userDao"/>
    </bean>

</beans>

其實只要注意對象的注入的時候,後面那個標籤不是value,而是 ref 就好了!

測試:

public class TestDemo3 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("屬性的注入/複雜屬性的注入/nature3.xml");
        UserService userService = (UserService)context.getBean("userService");
        userService.add();
    }
}

在這裏插入圖片描述

下來就是數組、List、map和properties屬性的注入了:

需要創建對象的類是Student3:

public class Student3 {
    private String name;
    private String[] str;
    private List<String> list;
    private Map<String,String> map;
    private Properties properties;

    public void setName(String name) {
        this.name = name;
    }

    public void setStr(String[] str) {
        this.str = str;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    @Override
    public String toString() {
        return "Student3{" +
                "name='" + name + '\'' +
                ", 數組=" + Arrays.toString(str) +
                ", list=" + list +
                ", map=" + map +
                ", properties=" + properties +
                '}';
    }
}

他的配置文件nature4.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-3.0.xsd">

    <!--數組屬性的注入-->
    <bean id="student1" class="com.tulun.bean.Student3">
        <property name="str">
            <list>
                <value>1</value>
                <value>2</value>
            </list>
        </property>
    </bean>

    <!--list屬性的注入-->
    <bean id="student2" class="com.tulun.bean.Student3">
        <property name="list">
            <list>
                <value>張三</value>
                <value>李四</value>
            </list>
        </property>
    </bean>

    <!--map屬性的注入-->
    <bean id="student3" class="com.tulun.bean.Student3">
        <property name="map">
            <map>
                <entry key="tulun" value="lzq"></entry>
                <entry key="tulun" value="lcx"></entry>
            </map>
        </property>
    </bean>

    <!--properties屬性的注入-->
    <bean id="student4" class="com.tulun.bean.Student3">
        <property name="properties">
            <props>
                <prop key="DriverClass">com.mysql.jdbc.Driver</prop>
            </props>
        </property>
    </bean>
</beans>

測試:

public class TestDemo4 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("屬性的注入/複雜屬性的注入/nature4.xml");
        test1(context);
        test2(context);
        test3(context);
        test4(context);
    }

    //測試數組
    private static void test1(ApplicationContext context) {
        Student3 student = (Student3)context.getBean("student1");
        System.out.println(student.toString());
    }

    //測試list
    private static void test2(ApplicationContext context) {
        Student3 student = (Student3)context.getBean("student2");
        System.out.println(student.toString());
    }

    //測試map
    private static void test3(ApplicationContext context) {
        Student3 student = (Student3)context.getBean("student3");
        System.out.println(student.toString());
    }

    //測試文件
    private static void test4(ApplicationContext context) {
        Student3 student = (Student3)context.getBean("student4");
        System.out.println(student.toString());
    }
}

在這裏插入圖片描述

IOC的使用(基於註解)

使用步驟:

  1. 引入依賴;
  2. 配置XML文件,開啓掃描類;
  3. 創建對應的類,添加註解,一般用@Component;
  4. 測試使用;

依賴和上面的一樣;

在常用的註解@Component下還衍生了三個註解:

  • @Controller(Web層);
  • @Service(業務層);
  • @Repository(dao層);

他們的作用都是一樣的,只是這樣是各層之間有了很高的區分度;

依賴注入的方式:

對象的依賴注入:

  • @Autowired
  • @Resource

簡單類型(基本屬性)的依賴注入:

  • @Value

代碼示例:

創建類:

@Component(value = "user")
@Scope(value = "singleton")  //設置單例
//相當於配置實現時裏面的id  <bean id = "user" ...
public class User {
    @Value(value = "1")   //簡單屬性的注入
    private int id;

    public void add() {
        System.out.println("User.add()"+id);
    }
}

註解實現的配置文件,bean4.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 開啓掃描 對包進行掃描,找相關的有註解的類,把這個類進行裝配-->
    <context:component-scan base-package="com.tulun1"></context:component-scan>

</beans>

測試,測試我用的額 junit,它的 jar 包如下:

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

測試代碼:

public class TestDemo1 {
    @Test
    public void test1() {
        ApplicationContext context = new ClassPathXmlApplicationContext("註解實現/bean4.xml");
        User user = (User)context.getBean("user");
        user.add();
    }
}

在這裏插入圖片描述
再來一個:

創建一個類:

@Component(value = "userService")
public class UserService {
    @Autowired
    //@Resource  //這個也可以 需要添加參數的話就是User那個類註解裏面的
    private User user; //這個User就是上面示例中的那個

    public void add() {
        user.add();
    }
}

測試:

public class TestDemo2 {
    @Test
    public void test1() {
        ApplicationContext context = new ClassPathXmlApplicationContext("註解實現/bean4.xml");
        UserService userService = (UserService) context.getBean("userService");
        userService.add();
    }
}

在這裏插入圖片描述
所以拿註解來實現的話,就顯得特別簡單,而在IOC中,配置和註解一般是聯合使用的,其中:

  • 創建對象(bean的實例化)是通過配置實現的;
  • 依賴注入是通過註解實現的;

下面是一個配置和註解聯合使用的例子,有三層(Controller、Service、Dao),其中,Controller層中有Service層的對象,Service層中有Dao層對象,那麼代碼如下:

創建Dao層類:

public class TestDao {
    @Value(value = "1")
    private int test;

    public void setTest(int test) {
        this.test = test;
    }

    public void test() {
        System.out.println("TestDao.test()"+test);
    }
}

創建Service層類:

public class TestService {
    @Autowired
    private TestDao testDao;

    public void setTestDao(TestDao testDao) {
        this.testDao = testDao;
    }

    public void test() {
        testDao.test();
    }
}

創建Controlller層類:

public class TestController {
    @Resource
    private TestService testService;

    public void setTestService(TestService testService) {
        this.testService = testService;
    }

    public void test() {
        testService.test();
    }
}

因爲是配置和註解的聯合使用,所以需要在配置文件中開啓掃描、創建對象,那麼bean5.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 開啓掃描 對包進行掃描,找相關的有註解的類,把這個類進行裝配-->
    <context:component-scan base-package="com.tulun1"></context:component-scan>

    <!--創建dao層對象-->
    <bean id="dao" class="com.tulun1.dao.TestDao"></bean>

    <!--創建service層對象-->
    <bean id="service" class="com.tulun1.service.TestService">
        <property name="testDao" ref="dao"></property>
    </bean>

    <!--創建controller層對象-->
    <bean id="controller" class="com.tulun1.controller.TestController">
        <property name="testService" ref="service"></property>
    </bean>
</beans>

測試:

public class TestDemo3 {
    @Test
    public void test1() {
        ApplicationContext context = new ClassPathXmlApplicationContext("配置和註解聯合使用/bean5.xml");
        TestController testController = (TestController)context.getBean("controller");
        testController.test();
    }
}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章