Spring 框架的概述以及Spring中基於XML的IOC配置

Spring 框架的概述以及Spring中基於XML的IOC配置

1、簡介

  1. Spring的兩大核心:IOC(DI)與AOP,IOC是反轉控制,DI依賴注入
  2. 特色:輕量級、依賴注入、面向切面編程、容器、框架、一站式
  3. 優點:
    1. 方便解耦:作到編譯期不依賴,運行期才依賴
    2. AOP的支持
    3. 聲明式事務的支持
    4. 方便程序的測試
    5. 方便整合各類框架
    6. 下降JavaEE API的使用難度
    7. Spring源碼很厲害

解耦:java

  • 耦合包括:類之間的和方法之間的spring

  • 解決的思路:
    1. 在建立對象的時候用反射來建立,而不是new
    2. 讀取配置文件來獲取要建立的對象全限定類名
  • Bean:在計算機英語中有可重用組件的含義
  • javabean(用java語言編寫的可重用組件)>實體類shell

2、工廠類解耦

在類中直接new的方法,耦合性太過於高,那麼不如將這件事情交給一個工廠類來解決。編程

如下,咱們將爲全部的Bean建立一個工廠類,BeanFactory。app

/**
 * Bean:可重用組件
 */
public class BeanFactory {
   private static Properties props;
    //靜態代碼塊
    static{
        try {
            //1.實例化Properties對象
            props=new Properties();
            //2.獲取Properties文件的流對象
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);
        }
        catch (Exception e){
            throw new ExceptionInInitializerError("初始化properties失敗");
        }

    }
}

BeanFactory初始化時,將從配置文件bean.properties中,獲取Properties元素。框架

接下來實現getBean方法,根據Properties方法獲取組件路徑,並建立對象。函數

/**
     * 根據bean的名稱獲取bean對象
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName){
        Object bean = null;

        try {
            String beanPath = props.getProperty(beanName);
            bean = Class.forName(beanPath).newInstance();
        }catch (Exception e){
            e.printStackTrace();
        }

        return bean;
    }

之後就可使用BeanFactory的類方法進行對象建立。測試

//    IAccountDao accountDao=new AccountDaoImpl();
    IAccountDao accountDao = (IAccountDao) BeanFactory.getBean("accountDao");

3、單例模式

而後有一個問題是:每次調用getBean方法,咱們都會建立一個BeanFactory對象,這裏徹底能夠替換成單例模式。code

在BeanFactory中定義一個Map容器,存放咱們須要建立的對象xml

private static Map<String,Object> beans;

接下來這樣修改就能獲得單例效果。

/**
 * Bean:可重用組件
 */
public class BeanFactory {
    private static Properties props;

    //容器
    private static Map<String,Object> beans;

    //靜態代碼塊
    static{
        try {
            //1.實例化Properties對象
            props=new Properties();
            //2.獲取Properties文件的流對象
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);
            //3.容器實例化
            beans = new HashMap<String, Object>();
            //4.從配置文件中取出全部的key
            Enumeration<String> keys = (Enumeration)props.keys();
            //5.遍歷枚舉
            while(keys.hasMoreElements()){
                //取出每一個key
                String key = keys.nextElement();
                //根據key獲取value
                String beanPath = props.getProperty(key);
                Object value = Class.forName(beanPath);
                //存放容器
                beans.put(key,value);
            }
        }
        catch (Exception e){
            throw new ExceptionInInitializerError("初始化properties失敗");
        }

    }

    /**
     * 根據bean的名稱獲取bean對象
     * @param beanName
     * @return
     */
//    public static Object getBean(String beanName){
//        Object bean = null;
//
//        try {
//            String beanPath = props.getProperty(beanName);
//            bean = Class.forName(beanPath).newInstance();
//        }catch (Exception e){
//            e.printStackTrace();
//        }
//
//        return bean;
//    }
    public static Object getBean(String beanName){
        return beans.get(beanName);
    }
}

4、IOC(反轉控制 Inversion of Control)

//        IAccountService accountService=new AccountServiceImpl();
        IAccountService accountService = (IAccountService) BeanFactory.getBean("accountService");

這兩行代碼的區別很能體現出IOC的思想。

區別:

  • 通常狀況:App直接向各類資源進行請求
  • IOC:App向工廠進行請求,工廠與資源進行聯繫,工廠控制資源。

5、Spring中的IOC

以上是咱們本身實現的IOC,這一切若是使用Spring的話,它將幫咱們解決,因此咱們學會了IOC的原理,接下來學Spring的用法。

刪除掉上面的BeanFactory,這個由Spring來作。

  • 在pom.xml中導入spring
<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
</dependency>
  • 在resources下建立beans.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

建立bean:(bean標籤的tag 」id「寫bean的名字,」class「寫bean的全限定類名)

<bean id="accountDao" class="com.mmj.dao.impl.AccountDaoImpl"></bean>
    <bean id="accoutService" class="com.mmj.service.impl.AccountServiceImpl"></bean>
  • 初始化容器
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

note:要用Spring的5.0.2版本,其餘版本代碼不太同樣。

public class Client {
    /**
     * 獲取Spring的ioc。根據id獲取對象
     * @param args
     */
    public static void main(String[] args) {
//        IAccountService accountService=new AccountServiceImpl();
        //1. 獲取核心容器對象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        IAccountService accountService = (IAccountService) context.getBean("accountService");
        System.out.println(accountService);
        IAccountService accountService2 = (IAccountService) context.getBean("accountService");
        System.out.println(accountService2);
        //accountService.saveAccount();
    }
}

輸出結果

com.mmj.service.impl.AccountServiceImpl@58134517
com.mmj.service.impl.AccountServiceImpl@58134517

5.1 ApplicationContext三個經常使用實現類

  1. ClassPathXmlApplicationContext:加載類路徑下的配置文件
  2. FileSystemXmlApplicationContext:加載磁盤任意位置文件(有權限)
  3. AnnotationConfigApplicationContext:它是用於讀取註解建立容器的

但Spring的容器ApplicationContextBeanFactory有一些不一樣。

  • ApplicationContext建立容器使用的策略是當即加載的方式,也就是一讀取配置文件,就立刻建立配置中的文件。
  • BeanFactory建立容器的時候,使用的是延遲加載的方式。也就是何時根據id建立對象了,纔是真正建立對象的時候。
public static void main(String[] args) {
////        IAccountService accountService=new AccountServiceImpl();
//        //1. 獲取核心容器對象
//        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//        IAccountService accountService = (IAccountService) context.getBean("accountService");
//        System.out.println(accountService);
//        IAccountService accountService2 = (IAccountService) context.getBean("accountService");
//        System.out.println(accountService2);
//        //accountService.saveAccount();
        Resource resource = new ClassPathResource("beans.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);
        IAccountService accountService = (IAccountService) beanFactory.getBean("accountService");
        System.out.println(accountService);
    }
}

這二者的區別在於:

  1. ApplicationContext在new的時候就已經初始化對象了,也就是在讀取配置文件後就開始建立了。
  2. BeanFactory加載完配置文件尚未建立對象,而是在調用getBean,使用到對象的時候纔開始建立。

所以:ApplicationContext適用於單例模式(更多),BeanFactory適用於多例模式

5.2 Spring中對Bean的管理細節

1. 建立bean的三種方式

<!--第一種方式,使用組件默認構造函數建立,若是沒有默認構造函數就會報錯-->
<bean id="accountDao" class="com.mmj.dao.impl.AccountDaoImpl"></bean>
<!--第二種方式,使用普通工廠方法建立對象(使用某個類中的方法建立對象,而且存入容器)-->
<bean id="beanFactory" class="com.mmj.factory.InstanceFactory"></bean>
<bean id="accountDao" factory-bean="beanFactory" factory-method="getDao"></bean>
<!--第三種方式,使用工廠中的靜態方法建立-->
<bean id="accountDao" class="com.mmj.factory.StaticFactory" factory-method="getStaticDao"></bean>

2. bean對象的做用範圍

3. bean對象的生命週期

相關文章
相關標籤/搜索