1. 程式人生 > >【JavaEE學習筆記】Spring_01_工廠模式,Spring小程式,IoC控制反轉

【JavaEE學習筆記】Spring_01_工廠模式,Spring小程式,IoC控制反轉

Spring_01

A.工廠模式

1.概述

是由專家總結出來的,在某種情況下解決某類問題的最佳解決方案

設計模式六大原則

單一職責原則

里氏替換原則

依賴倒置原則

介面隔離原則

迪米特法則

開閉原則

2.框架

是用於處理某種問題的半成品軟體,共開發人員通過制定進行高效的開發

3.JavaSE的設計模式

什麼是GOF(四人幫,全拼 Gang of Four)

在1994年由四人合著出版了一本名為

Design Patterns - Elements of Reusable Object-Oriented Software

(設計模式 - 可複用的面向物件軟體元素)的書

該書首次提到了軟體開發中設計模式的概念

GOF總結了JavaSE開發中常見的23種設計模式,可以分為3大類:

建立型模式、結構型模式、行為型模式

4.JavaEE模式

JavaEE設計模式特別關注表示層,如MVC模式(MVC Pattern)

資料訪問物件模式DAO(Data Access Object Pattern) 

前端控制器模式(Front Controller Pattern)

5.Spring應用總體概述


6.Spring的核心思想(就是工廠模式)

不重複發明輪子理論

錘子理論

7.OOP

核心是面向抽象程式設計,面向抽象程式設計的核心是面向介面

a.IUSerDao介面

public interface IUserDao {
	void save(UserMBean user);
}

b.UserDaoImpl實現類

public class UserDaoImpl implements IUserDao {

	@Override
	public void save(UserMBean user) {
		
	}

}

介面的實現可能有多個,如何實現在多個介面具體實現之間進行切換

工廠模式

c.DaoFactory工廠

這是一種因為只有一種具體實現的退化寫法

不是真正GOF提出的工廠設計模式

靜態工廠方法[不是GOF的工廠模式]

public class DaoFactory {

	public static IUserDao getUserDao(String type) {
		if ("oracle".equals(type)) {
			return new OracleUserDaoImpl();
		}
		if ("mysql".equals(type)) {
			return new MysqlUserDaoImpl();
		}

		return new UserDaoImpl();
	}

}

8.工廠模式

設計模式屬於建立型模式,它提供了一種建立物件的最佳方式

主要解決:主要解決介面實現的選擇問題

優點:

一個呼叫者想建立一個物件,只要知道其名稱就可以了

擴充套件性高,如果想增加一個產品,只要擴充套件一個工廠類就可以

遮蔽產品的具體實現,呼叫者只關心產品的介面

缺點:

每次增加一個產品時,都需要增加一個具體類和物件實現工廠

使得系統中類的個數成倍增加,在一定程度上增加了系統的複雜度

同時也增加了系統具體類的依賴,這並不是什麼好事


9.抽象工廠模式

是圍繞一個超級工廠建立其他工廠,該超級工廠又稱為其他工廠的工廠

這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式

主要解決:提供一個建立一系列相關或相互依賴物件的介面,解決介面實現選擇的問題

優點:

當一個產品族中的多個物件被設計成一起工作時

它能保證客戶端始終只使用同一個產品族中的物件

缺點:

產品族擴充套件非常困難,要增加一個系列的某一產品

既要在抽象的 Creator 里加程式碼,又要在具體的裡面加程式碼


10.Spring底層實現

引入資原始檔,使用反射建立字串所指代的物件

Spring框架最重要是提供了以類似下面xml+BeanFactory的方式

管理配置在xml檔案中的受管Bean

抽象產品介面IShape

package org.wpf.fac;

// 抽象產品介面
public interface IShape {
	void draw();
}
具體產品1 Circle
package org.wpf.fac;

public class Circle implements IShape {

	@Override
	public void draw() {
		System.out.println("畫一個圓形");
	}

}

擴充套件顏色 IColor

package org.wpf.fac;

public interface IColor {
	void fill();
}

顏色實現 Red

package org.wpf.fac;

public class Red implements IColor {

	@Override
	public void fill() {
		System.out.println("紅色代表熱情");
	}

}

具體產品2 Sequare

package org.wpf.fac;

public class Sequare implements IShape {

	@Override
	public void draw() {
		System.out.println("繪製矩形");
	}

}

工廠 BeanFactory

package org.wpf.fac;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.naming.factory.BeanFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class BeanFactory {
	// 需求,當載入BeanFactory類時,則自動解析xml檔案,並構建class所指定的類物件,以id值為key存放在一個集合中,
	// 每次獲取產品實現時,只需要在集合中進行查詢即可
	private static Map<String, Object> map = new HashMap<>();

	static {
		init();
	}

	private BeanFactory() {
	}

	public static Object getBean(String id) {
		if (map.containsKey(id)) {
			return map.get(id);
		}
		return null;
	}

	// 使用JAXP
	private static void init() {
		try {
			InputStream is = BeanFactory.class.getResourceAsStream("beans.xml");
			SAXParserFactory fac = SAXParserFactory.newInstance();
			// 獲取當前系統預設使用的xml檔案解析器
			SAXParser parser = fac.newSAXParser();
			parser.parse(is, new DefaultHandler() {
				@Override
				public void startElement(String uri, String localName, String qName, Attributes attributes)
						throws SAXException {
					// 引數uri是名空間,localName是xml標籤的本地名,qName是xml標籤的全域性名稱,attributes是標籤的所有屬性,存放方式類似於Map
					if ("bean".equals(qName)) {
						String id = attributes.getValue("id");// 獲取<bean>標籤中的id屬性值
						String className = attributes.getValue("class");
						try {
							Object obj = Class.forName(className).newInstance();
							map.put(id, obj);
						} catch (Exception e) {
							throw new SAXException(e);
						}
					}
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

配置檔案beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 避免properties檔案的缺點,xml配置檔案可以通過dtd或者xsd的方式定義其中的語法規則 -->
<beans>
	<!-- bean配置,id表示不允許重複,這是名稱,class是具體實現類的全名 -->
	<bean id="color" class="org.wpf.fac.Red"/>
	<bean id="shape" class="org.wpf.fac.Sequare"/>
</beans>

測試類

package org.wpf.fac;

public class Test {
	public static void main(String[] args) {
		IColor c = (IColor) BeanFactory.getBean("color");
		c.fill();
		
		IShape s = (IShape) BeanFactory.getBean("shape");
		s.draw();
	}
}

B.Spring初識

1.jar包

Spring最新為5.0.0 RC4,目前常用的是4.3.12 (2017年9月),目前支援JDK8/7/6等

beans、core、context、context-support和expression

[提供了一種表示式語言SpEL以簡化配置檔案]

實際上壓縮檔案中只包含Spring的jar包,

包含需要依賴的包  commons-logging


2.定義核心配置

src/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">

	<!-- id:受管理bean的名稱,不重複 class:全類名 -->
	<bean id="color" class="org.wpf.spr.Red" />
</beans>

3.編碼呼叫

package org.wpf.spr;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

@SuppressWarnings("deprecation")
public class Test {
	public static void main(String[] args) {
		// 讀取配置檔案
		Resource r = new ClassPathResource("applicationContext.xml");
		
		// 獲取工廠
		BeanFactory fac = new XmlBeanFactory(r);
		
		IColor c = (IColor) fac.getBean("color");
		c.fill();
	}
}

4.Spring的IoC容器將面向介面的程式設計代價降到了最低

C.IoC控制反轉

1.Spring概述

Spring是一個輕量級的控制反轉IoC/DI依賴注入和麵向切面AOP的開源容器框架

是一個開源的Java/Java EE全功能棧full-stack的應用程式框架

以Apache許可證形式釋出,它由Rod Johnson建立

它是為了解決企業應用開發的複雜性而建立的

2002年Rod Johnson在他的Expert One-On-One Java EE Design and Development

一書中首次釋出了這個框架,並奠定了作者的大師地位

該框架也可以移植到.NET的環境下

Spring框架本身並沒有強制實行任何特別的程式設計模式

在Java社群裡,Spring作為EJB模型之外的另外一個選擇甚至是替代品而廣為流行

從設計上看,Spring給予了Java程式設計師許多的自由度

但同時對業界常見的問題也提供了良好的文件和易於使用的方法

Spring框架的核心功能在任何Java應用中都是適用的

在基於Java企業平臺上的web應用中,大量的拓展和改進得以形成

為此,Spring獲得了廣泛的歡迎,並被許多公司認可為具有戰略意義的重要框架

Spring使用基本的JavaBean來完成以前只可能由EJB完成的事情

[宣告式事務管理  SessionBean會話bean用於封裝業務處理邏輯 

EntityBean實體bean用於封裝資料訪問邏輯{BMP是bean管理的持久化

CMP容器管理的持久化} MessageDrivenBean訊息驅動bean

用於實現非同步的邏輯處理]

然而,Spring的用途不僅限於伺服器端的開發

從簡單性、可測試性和鬆耦合的角度而言,任何Java應用都可以從Spring中受益

簡單來說,Spring是一個分層的JavaSE/EE full-stack(一站式解決方案)

輕量級開源框架

2.發展歷程

2000年Spring框架最開始的部分是由Rod Johnson於2000年

為倫敦的金融界提供獨立諮詢業務時寫出來的

在2002年編著的《Expert one on one J2EE design and development》一書中

對Java EE 系統框架臃腫、低效、脫離現實的種種現狀提出了質疑

並積極尋求探索革新之道,釋出了自己的程式碼(interface21)

以闡述“如何讓應用程式能以超出當時大眾所慣於接受的易用性

和穩定性與J2EE平臺上的不同元件合作”的觀點

2003年2月,一批自願拓展Spring框架的程式開發人員組成了團隊

在Sourceforge上構建了一個專案

2003年6月,Spring的框架首次在Apache 2.0的使用許可中釋出

2004年3月在Spring框架上工作了一年之後,這個團隊釋出了第一個版本(1.0)

2005年,Spring框架的開發人員成立了自己的公司

來提供對Spring的商業支援,其中最顯著的就是與BEA的合作

2009年VMware以4.2億美元收購SpringSource,Spring開始向雲端計算方向發展

通過與VMware的合作計劃為資料中心、私有云及公共雲建立一個獨立、整合

同時又融合了構建、執行及管理於一身的解決方案

Springboot  springdata springcloud

3.Maven進行Spring基礎程式設計

建立Web工程,配置pom.xml檔案

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.wpf</groupId>
	<artifactId>spr</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>spr Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<!-- 編碼 -->
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
	</properties>
	<dependencies>
		<!-- Spring框架 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>4.3.14.RELEASE</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<!-- jdk1.8 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
		<finalName>spr</finalName>
	</build>
</project>

定義對應的類,並進行配置,將物件納入到容器中進行管理(使用Date)

<?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="now" class="java.util.Date" />
	
	<!-- id,name命名比較隨意,一般按照java變數命名規則 -->
	<bean id="123d" name="555" class="java.util.Date" scope="prototype" />
	
	<bean id="df" class="java.text.SimpleDateFormat" >
		<!-- 自定義日期格式,通過反射,必須要有無參構造方法 -->
		<constructor-arg value="yyyy-MM-dd" />
	</bean>
</beans>

獲取IoC容器的引用

package spr;

import java.text.DateFormat;
import java.util.Date;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

@SuppressWarnings("deprecation")
public class Test_01 {
	public static void main(String[] args) {
		// 獲取IoC容器的引用
		Resource r = new ClassPathResource("applicationContext.xml");
		
		// 獲取工程
		BeanFactory fac = new XmlBeanFactory(r);
		
		// 從IoC容器中通過名稱獲取配置在IoC容器中的受管bean
		Date dd = (Date) fac.getBean("now");
		DateFormat df = (DateFormat) fac.getBean("df");
		
		// 呼叫受管bean物件的方法完成業務邏輯處理
		System.out.println(df.format(dd));
	}
}

4.ApplicationContext

上面的程式碼中可以看到,XmlBeanFactory已被廢棄

不建議使用,所以,建議使用ApplicationContext

package spr;

import java.text.DateFormat;
import java.util.Date;

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

public class Test_01 {
	public static void main(String[] args) {
		// 獲取IoC容器的引用
		ApplicationContext fac = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		// 從IoC容器中通過名稱獲取配置在IoC容器中的受管bean
		Date dd = fac.getBean("555", Date.class);
		DateFormat df = (DateFormat) fac.getBean("df");
		
		// 呼叫受管bean物件的方法完成業務邏輯處理
		System.out.println(df.format(dd));
	}
}
ApplicationContext介面繼承於BeanFactory介面

主要用於引用IoC/DI容器

ApplicationContext具有BeanFactory的所有功能

另外提供針對企業級開發的功能支援

5.getBean(Class<T>)

T在IoC容器中按照型別查詢所有的受管bean物件

如果一個型別有2個受管配置(id重複),則按型別查找出錯

NoUniqueBeanDefinitionException

6.T getBean(String受管bean名稱, Class<T>目標型別)

返回以給定名稱註冊的Bean,返回的Bean將被cast給定的類

如Bean不能被Cast,異常BeanNotOfRequiredTypeException將被丟擲

Date dd = fac.getBean("555", Date.class)

7.其他不重要的方法

boolean containsBean(String受管bean的名稱):

如果BeanFactory包含符合給定名稱的Bean定義或Bean例項,則返回true

Class getType(String name受管bean的名稱):

返回給定名稱的Bean的 Class

如果對應的Bean找不到,則會丟擲NoSuchBeanDefinitionException異常

boolean isSingleton(String):

決定在給定名稱時,Bean定義或Bean例項註冊是否為單例模式

如果對應的Bean不能被找到,則丟擲異常

String[] getAliases(String):

如果在Bean的定義中有定義,則返回給定Bean名稱的別名

8.配置檔案中的命名規則

在配置檔案中使用id屬性定義受管bean的名稱

一般建議採用Java變數的命名規則,實際上使用123d或者12,3d都是可以的

需要注意Spring版本的區別,id只能定義一個名稱

如果需要定義多個可以使用name屬性進行定義

這裡使用id、name名稱都可以獲取受管bean

針對獲取受管bean物件的名稱而言,其它的名稱都叫做別名

Id命名建議採用Java變數的命名機制

注意Spring3-id命名規範比較嚴格

Spring3+命名中允許數字開頭,允許使用包括空格在內的特殊符號

但是注意的是id只有一個名字,name允許使用特殊符號,是多個名稱

id命名中空格是名稱的一部分,name可以使用空格或者逗號分隔多個名稱

<bean id="123d" name="/dd.do 555" class="java.util.Date" />

9.受管bean

受管bean就是納入到IoC/DI容器中,由容器負責建立和管理生命週期的javabean物件

Xml配置受管bean   applicationContext.xml

<bean

id=”受管bean的識別符號,唯一,這裡只能定義一個名稱”

class=”受管bean類的全名”

name=”別名,可以定義多個,使用逗號分隔”

scope=”範圍,可以設定,預設singleton單例

[Spring容器預設提供了單例模式的實現,不需要編碼]

prototype原型,每次獲取的都是新建的物件

另外還有和web相關的3個配置request、session、global session”/>

受管bean的要求:一般來說任何java類都可以作為受管bean

Spring中那些組成應用的主體以及由Spring IoC容器所管理的物件被稱之為bean

Bean就是由Spring容器初始化、裝配以及被管理的物件

bean是Spring管理的基本單位,在Spring的應用中

所有的元件都是bean,bean包括資料來源,Hibernate的SessionFactory及事務管理器等

Spring裡的bean是非常廣義的概念,任何的Java物件

Java元件都可被當成bean處理,甚至這些元件並不是標準的JavaBean

10.BeanFactory和ApplicationContext的關係

BeanFacotry是spring中比較原始的Factory,提供了IoC/DI容器使用的最基本的方法

ApplicationContext介面由BeanFactory介面派生而來

在提供BeanFactory所有的功能基礎上提供了企業級應用開發的支援

例如讀取資原始檔、釋出事件等

BeanFactory針對單例的受管bean採用的是延遲載入

ApplicationContext採用的是立即載入【所有的prototype受管bean都是延遲】

所以BeanFactory一般用於記憶體敏感的受限環境開發中,ApplicationContext一般使用

11.4大原則

使用POJO進行輕量級和最小侵入式開發

POJO(Plain Ordinary Java Object)簡單的Java物件

實際就是普通JavaBeans,是為了避免和EJB混淆所創造的簡稱

通過控制反轉IoC、依賴注入DI和基於介面程式設計實現鬆耦合

通過AOP和預設慣例進行宣告式程式設計

使用AOP和模板程式設計減少模式化程式碼

12.主要功能

基於Java Beans的配置管理,採用IOC的原理,特別是對依賴注射技術的使用

這些都用來減少各元件間對實施細則的相互依賴性

一個核心的,全域性適用的bean工廠

一個一般抽象化的層面來管理資料庫間的資料處理

建立在框架內的,對Java資料處理API和單獨的JDBC資料來源的一般性策略

因此,在資料處理支援上對Java企業版本環境的依賴性得以消除

和一些整合持久化的框架,如Hibernate,JDO,iBATIS和db4o,的整合

web應用中的MVC框架,基於核心的Spring功能,支援多種產生檢視的技術

包括JSP,FreeMarker,Velocity,Tiles,iText,和POI

大量的AOP框架以提供諸如資料處理管理的服務

同IOC的功能一樣,目的是提高系統的模組化程度

13.基本框架結構

Spring是一種JavaEE開發中的一站式解決方案,所以其中包含的內容比較多

為了避免在應用中新增無用功能,所以Spring採用了非強制性的模組化結構

在具體應用中,可以根據應用所需要的功能進行選擇新增

a.Spring3.x分為6大模組,Spring的模組化是很強的

各個功能模組都是獨立的,可以選擇的使用


Core模組是Spring應用的基礎,提供了最基本的IoC/DI容器的支援和實現

AOP模組建立在Core模組的基礎上,提供了AOP技術的支援

以簡化AOP程式設計的複雜度

DAO和ORM模組建立在AOP的基礎上

DAO提供了dao模式程式設計的簡化支援,ORM提供了整合持久層框架的支援

同時在AOP的基礎上給資料庫訪問提供了宣告式事務的支援

JEE模組建立在Core模組的基礎上

提供了針對EJB\郵件javaMail等企業級應用支援

Web模組建立在core模組的基礎上

提供了整合其它表現層框架【例如Struts\JSF等】的支援

同時提出了自己的表現層框架SpringMVC[針對Struts1提出的]

b.Spring4.x分為6大模組,包括20多個子專案


Core container核心容器:beans core context context-support expression

AOP和apects提供AOP程式設計技術支援:

aop aspects,另外還有其它的不是Spring的jar

Data Access/Integration針對DAO程式設計和ORM整合的支援: jdbc orm tx

Web提供了整合表現層框架和對應的web解決方案SpringMVC:web webmvc

Instrumentation底層基礎,是一種沒有圖形介面的

具有啟動能力的,用於監控其他類的工具類

Test提供了單元測試的支援,要求junit4.8+版本

14.Spring的全方位應用程式框架


ssm=SpringMVC+Spring+MyBatis

[一般開發中常用,尤其是網際網路應用開發型別的公司,一般中小型快速開發中應用]

ssh[2]=Struts2+Spring+Hibernate 

[使用較少,一般在大型軟體公司中長期使用]