1. 程式人生 > >【javaWeb】第63天——Spring框架的第2天

【javaWeb】第63天——Spring框架的第2天

Spring框架第二天


課程回顧:Spring框架第一天

1. 概述
	* IOC和AOP
2. 框架的IOC的入門
	* 建立applicationContext.xml,引入約束,<bean/>	
	* 配置檔案<bean id="" class="" name="" scope=""/>	
3. 依賴注入
	* DI:依賴注入
4. 整合WEB
	* Spring框架提供解決方案,先匯入Spring-web.jar包,提供類

今天內容介紹

1. Spring框架的IOC基於註解的方式
2. Spring框架整合JUnit單元測試
3. AOP的概述
4. AOP的底層實現原理(瞭解)
5. AOP功能基於AspectJ的配置檔案方式

技術分析之Spring框架的IOC功能之註解的方式


Spring框架的IOC之註解方式的快速入門

1. 步驟一:匯入註解開發所有需要的jar包
	* 引入IOC容器必須的6個jar包
	* 多引入一個:Spring框架的AOP的jar包,spring-aop的jar包

2. 步驟二:建立對應的包結構,編寫Java的類
	* UserService			-- 介面
	* UserServiceImpl		-- 具體的實現類

3. 步驟三:在src的目錄下,建立applicationContext.xml的配置檔案,然後引入約束。注意:因為現在想使用註解的方式,那麼引入的約束髮生了變化
	* 需要引入context的約束,具體的約束如下
		<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.xsd
		        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here -->
			
		</beans>

4. 步驟四:在applicationContext.xml配置檔案中開啟元件掃描
	* Spring的註解開發:元件掃描
		<context:component-scan base-package="com.itheima.demo1"/>
		
	* 注意:可以採用如下配置
		<context:component-scan base-package="com.itheima"/> 這樣是掃描com.itheima包下所有的內容

5. 步驟五:在UserServiceImpl的實現類上添加註解
	* @Component(value="userService")	-- 相當於在XML的配置方式中 <bean id="userService" class="...">

6. 步驟六:編寫測試程式碼
	public class SpringDemo1 {
		@Test
		public void run1(){
			ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
			UserService us = (UserService) ac.getBean("userService");
			us.save();
		}
	}

Spring框架中Bean管理的常用註解

1. @Component:元件.(作用在類上)

2. Spring中提供@Component的三個衍生註解:(功能目前來講是一致的)
	* @Controller		-- 作用在WEB層
	* @Service			-- 作用在業務層
	* @Repository		-- 作用在持久層
	
	* 說明:這三個註解是為了讓標註類本身的用途清晰,Spring在後續版本會對其增強

3. 屬性注入的註解(說明:使用註解注入的方式,可以不用提供set方法)
	* 如果是注入的普通型別,可以使用value註解
		* @Value			-- 用於注入普通型別
	
	* 如果注入的是物件型別,使用如下註解
		* @Autowired		-- 預設按型別進行自動裝配
			* 如果想按名稱注入
			* @Qualifier	-- 強制使用名稱注入
	
	* @Resource				-- 相當於@Autowired和@Qualifier一起使用
		* 強調:Java提供的註解
		* 屬性使用name屬性

Bean的作用範圍和生命週期的註解

1. Bean的作用範圍註解
	* 註解為@Scope(value="prototype"),作用在類上。值如下:
		* singleton		-- 單例,預設值
		* prototype		-- 多例

2. Bean的生命週期的配置(瞭解)
	* 註解如下:
		* @PostConstruct	-- 相當於init-method
		* @PreDestroy		-- 相當於destroy-method

Spring框架整合JUnit單元測試

1. 為了簡化了JUnit的測試,使用Spring框架也可以整合測試
2. 具體步驟
	* 要求:必須先有JUnit的環境(即已經匯入了JUnit4的開發環境)!!
	
	* 步驟一:在程式中引入:spring-test.jar
	* 步驟二:在具體的測試類上添加註解
		@RunWith(SpringJUnit4ClassRunner.class)
		@ContextConfiguration("classpath:applicationContext.xml")
		public class SpringDemo1 {
			
			@Resource(name="userService")
			private UserService userService;
			
			@Test
			public void demo2(){
				userService.save();
			}
		}

案例一:使用AOP技術對DAO層操作進行增強功能


需求分析

1. 使用AOP技術對DAO層操作進行增強功能

技術分析之Spring框架的核心功能之AOP技術


AOP的概述

1. 什麼是AOP的技術?
	* 在軟體業,AOP為Aspect Oriented Programming的縮寫,意為:面向切面程式設計
	* AOP是一種程式設計正規化,隸屬於軟工範疇,指導開發者如何組織程式結構
	* AOP最早由AOP聯盟的組織提出的,制定了一套規範.Spring將AOP思想引入到框架中,必須遵守AOP聯盟的規範
	* 通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術
	* AOP是OOP的延續,是軟體開發中的一個熱點,也是Spring框架中的一個重要內容,是函數語言程式設計的一種衍生範型
	* 利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率

2. AOP:面向切面程式設計.(思想.---解決OOP遇到一些問題)
3. AOP採取橫向抽取機制,取代了傳統縱向繼承體系重複性程式碼(效能監視、事務管理、安全檢查、快取)

4. 為什麼要學習AOP
	* 可以在不修改原始碼的前提下,對程式進行增強!!	

Spring框架的AOP的底層實現

1. Srping框架的AOP技術底層也是採用的代理技術,代理的方式提供了兩種
	1. 基於JDK的動態代理
		* 必須是面向介面的,只有實現了具體介面的類才能生成代理物件
	
	2. 基於CGLIB動態代理
		* 對於沒有實現了介面的類,也可以產生代理,產生這個類的子類的方式

2. Spring的傳統AOP中根據類是否實現介面,來採用不同的代理方式
	1. 如果實現類介面,使用JDK動態代理完成AOP
	2. 如果沒有實現介面,採用CGLIB動態代理完成AOP

JDK的動態代理(程式碼瞭解,理解原理)

1. 使用Proxy類來生成代理物件的一些程式碼如下:
	/**
	 * 使用JDK的方式生成代理物件
	 * @author Administrator
	 */
	public class MyProxyUtils {
		public static UserDao getProxy(final UserDao dao) {
			// 使用Proxy類生成代理物件
			UserDao proxy = (UserDao) Proxy.newProxyInstance(dao.getClass().getClassLoader(),
					dao.getClass().getInterfaces(), new InvocationHandler() {
						
						// 代理物件方法一直線,invoke方法就會執行一次
						public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
							if("save".equals(method.getName())){
								System.out.println("記錄日誌...");
								// 開啟事務
							}
							// 提交事務
							// 讓dao類的save或者update方法正常的執行下去
							return method.invoke(dao, args);
						}
					});
			// 返回代理物件
			return proxy;
		}
	}

CGLIB的代理技術(程式碼瞭解)

1. 引入CBLIB的開發包
	* 如果想使用CGLIB的技術來生成代理物件,那麼需要引入CGLIB的開發的jar包,在Spring框架核心包中已經引入了CGLIB的開發包了。所以直接引入Spring核心開發包即可!

2. 編寫相關的程式碼
	public static OrderDaoImpl getProxy(){
		// 建立CGLIB核心的類
		Enhancer enhancer = new Enhancer();
		// 設定父類
		enhancer.setSuperclass(OrderDaoImpl.class);
		// 設定回撥函式
		enhancer.setCallback(new MethodInterceptor() {
			@Override
			public Object intercept(Object obj, Method method, Object[] args,
					MethodProxy methodProxy) throws Throwable {
				if("save".equals(method.getName())){
					// 記錄日誌
					System.out.println("記錄日誌了...");
				}
				return methodProxy.invokeSuper(obj, args);
			}
		});
		// 生成代理物件
		OrderDaoImpl proxy = (OrderDaoImpl) enhancer.create();
		return proxy;
	}

Spring基於AspectJ的AOP的開發


技術分析之AOP的相關術語

1. Joinpoint(連線點)	-- 所謂連線點是指那些被攔截到的點。在spring中,這些點指的是方法,因為spring只支援方法型別的連線點
2. Pointcut(切入點)		-- 所謂切入點是指我們要對哪些Joinpoint進行攔截的定義
3. Advice(通知/增強)	-- 所謂通知是指攔截到Joinpoint之後所要做的事情就是通知.通知分為前置通知,後置通知,異常通知,最終通知,環繞通知(切面要完成的功能)
4. Introduction(引介)	-- 引介是一種特殊的通知在不修改類程式碼的前提下, Introduction可以在執行期為類動態地新增一些方法或Field
5. Target(目標物件)		-- 代理的目標物件
6. Weaving(織入)		-- 是指把增強應用到目標物件來建立新的代理物件的過程
7. Proxy(代理)		-- 一個類被AOP織入增強後,就產生一個結果代理類
8. Aspect(切面)			-- 是切入點和通知的結合,以後咱們自己來編寫和配置的

技術分析之AspectJ的XML方式完成AOP的開發

1. 步驟一:建立JavaWEB專案,引入具體的開發的jar包
	* 先引入Spring框架開發的基本開發包
	* 再引入Spring框架的AOP的開發包
		* spring的傳統AOP的開發的包
			* spring-aop-4.2.4.RELEASE.jar
			* com.springsource.org.aopalliance-1.0.0.jar
		
		* aspectJ的開發包
			* com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
			* spring-aspects-4.2.4.RELEASE.jar

2. 步驟二:建立Spring的配置檔案,引入具體的AOP的schema約束
	<beans xmlns="http://www.springframework.org/schema/beans"
	       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	       xmlns:aop="http://www.springframework.org/schema/aop"
	       xsi:schemaLocation="
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

3. 步驟三:建立包結構,編寫具體的介面和實現類
	* com.itheima.demo2
		* CustomerDao			-- 介面
		* CustomerDaoImpl		-- 實現類

4. 步驟四:將目標類配置到Spring中
	<bean id="customerDao" class="com.itheima.demo3.CustomerDaoImpl"/>

5. 步驟五:定義切面類
	public class MyAspectXml {
		// 定義通知
		public void log(){
			System.out.println("記錄日誌...");
		}
	}

6. 步驟六:在配置檔案中定義切面類
	<bean id="myAspectXml" class="com.itheima.demo3.MyAspectXml"/>

7. 步驟七:在配置檔案中完成aop的配置
	<aop:config>
		<!-- 引入切面類 -->
		<aop:aspect ref="myAspectXml">
			<!-- 定義通知型別:切面類的方法和切入點的表示式 -->
			<aop:before method="log" pointcut="execution(public * com.itheima.demo3.CustomerDaoImpl.save(..))"/>
		</aop:aspect>
	</aop:config>

8. 完成測試
	@RunWith(SpringJUnit4ClassRunner.class)
	@ContextConfiguration("classpath:applicationContext.xml")
	public class Demo3 {
		@Resource(name="customerDao")
		private CustomerDao customerDao;
		@Test
		public void run1(){
			customerDao.save();
			customerDao.update();
			customerDao.delete();
		}
	}

切入點的表示式

1. 再配置切入點的時候,需要定義表示式,重點的格式如下:execution(public * *(..)),具體展開如下:
	* 切入點表示式的格式如下:
		* execution([修飾符] 返回值型別 包名.類名.方法名(引數))
	
	* 修飾符可以省略不寫,不是必須要出現的。
	* 返回值型別是不能省略不寫的,根據你的方法來編寫返回值。可以使用 * 代替。
	* 包名例如:com.itheima.demo3.BookDaoImpl
		* 首先com是不能省略不寫的,但是可以使用 * 代替
		* 中間的包名可以使用 * 號代替
		* 如果想省略中間的包名可以使用 .. 
	
	* 類名也可以使用 * 號代替,也有類似的寫法:*DaoImpl
	* 方法也可以使用 * 號代替
	* 引數如果是一個引數可以使用 * 號代替,如果想代表任意引數使用 ..

AOP的通知型別

1. 前置通知
	* 在目標類的方法執行之前執行。
	* 配置檔案資訊:<aop:after method="before" pointcut-ref="myPointcut3"/>
	* 應用:可以對方法的引數來做校驗

2. 最終通知
	* 在目標類的方法執行之後執行,如果程式出現了異常,最終通知也會執行。
	* 在配置檔案中編寫具體的配置:<aop:after method="after" pointcut-ref="myPointcut3"/>
	* 應用:例如像釋放資源

3. 後置通知
	* 方法正常執行後的通知。		
	* 在配置檔案中編寫具體的配置:<aop:after-returning method="afterReturning" pointcut-ref="myPointcut2"/>
	* 應用:可以修改方法的返回值

4. 異常丟擲通知
	* 在丟擲異常後通知
	* 在配置檔案中編寫具體的配置:<aop:after-throwing method="afterThorwing" pointcut-ref="myPointcut3"/>	
	* 應用:包裝異常的資訊

5. 環繞通知
	* 方法的執行前後執行。
	* 在配置檔案中編寫具體的配置:<aop:around method="around" pointcut-ref="myPointcut2"/>
	* 要注意:目標的方法預設不執行,需要使用ProceedingJoinPoint對來讓目標物件的方法執行。