Spring AOP實戰例子與springmvc整合不起效果的解決辦法


在使用AOP之前,首先我們先了解一下什么是AOP吧。在網上很多人將AOP翻譯為“面向切面編程”,什么是面向切面?與面向對象有什么區別呢?

在回答這兩個問題之前,我們先要明白切面的概念。

切面由切點與增強組成,它既包括了橫切邏輯的定義,也包括了連接點的定義,springAOP就是負責實施切面的框架,它將切面定義的橫切邏輯

織入到切面所指定的連接點中。

這時候就要問了:什么是切點?什么是增強?

先看個例子,在例子中再為大家一一解釋。

例子:在服務行業,熱情問好,帶人禮貌是每一個成熟的服務員應有的規范。

建立一個接口  Water.java 方法:問好與服務,greetTo(),serviceTo()

package test.aop;
/**
 * 
 * @author 作者: wcy  
 * @version 創建時間:Mar 3, 2015 4:27:12 PM
 * @Description: TODO(一個服務生向顧客問候接待)
 */
public interface Waiter {

	public void greetTo(String name);
	public void serviceTo(String name);
}

 那么接下來一個生澀的,訓練不足的服務員,他只會生硬的打招呼,這對客人的服務可不好。

建立一個類NativeWater.java

package test.aop.impl;

import test.aop.Waiter;

/**
 * 
 * @author 作者: wcy  
 * @version 創建時間:Mar 3, 2015 4:29:53 PM
 * @Description: TODO(一個訓練不足的服務生)
 */
public class NativeWater implements Waiter{

	public void greetTo(String name) {
		System.out.println("greet to :"+name+"....");
		
	}

	public void serviceTo(String name) {
		System.out.println("service to :"+name+"....");
		
	}

}

 這樣子不好,我們必須對訓練不足的服務員進行規范,在打招呼之前先熱情問好

package test.aop.impl;

import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;

/**
 * 
 * @author 作者: wcy  
 * @version 創建時間:Mar 3, 2015 4:32:39 PM
 * @Description: TODO(服務生打招呼前,友好問候別人)
 */
public class GreetingBeforeAdvice implements MethodBeforeAdvice{

	public void before(Method arg0, Object[] arg1, Object arg2)
			throws Throwable {
		String clientName = (String) arg1[0];
		System.out.println("How are you ? Mr."+clientName+"~~~~~");
	}

}

 好,已經對其進行規范了,我們就要測試一下:

package test.aop.impl;

import org.junit.Before;
import org.junit.Test;
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;

import test.aop.Waiter;

/**
 * 
 * @author 作者: wcy  
 * @version 創建時間:Mar 3, 2015 4:40:14 PM
 * @Description: TODO(強制服務生要熱情問候顧客)
 */
public class BeforeAdviceTest {

	private Waiter waiter;
	private BeforeAdvice advice;
	private ProxyFactory pf;
	
	@Before
	public void init(){
		waiter = new NativeWater();
		advice = new GreetingBeforeAdvice();
		pf = new ProxyFactory();//Spring工廠提供的代理類
		pf.setTarget(waiter);  	//設置代理目標
		pf.addAdvice(advice);//為代理目標添加增強
	}
	
	@Test
	public void test01(){
		
		Waiter proxy = (Waiter) pf.getProxy();
		proxy.greetTo("xiaoyu");
		proxy.serviceTo("xiaolian");
	}
}

 運行的結果如下:

How are you ? Mr.xiaoyu~~~~~
greet to :xiaoyu....
How are you ? Mr.xiaolian~~~~~
service to :xiaolian....

 

好了,這就是一個面向切面的簡單例子,那我們就要總結一下了,面向切面需要什么東西。

1、目標類。也就是上文所說的NativeWater.java 該類是一個訓練不足的服務生,需要我們對其進行規范,所以要有規范類。

2、增強類。需要實現AOP的前置增強(同樣也有后置、環繞等增強),就是規范類,對服務生進行規范。

3、測試類。要為其進行代理,所以要有AOP的代理工廠。

詳細的AOP資料,百度很多我就不一一介紹了。

先說一下AOP的執行流程吧。

當我們調用某個定義了AOP的目標類中某個方法時,spring容器會為目標類生成代理類,這生成的方法有2種,一是:jdk的動態代理,使用它必須要有接口;二是CGLib代理,

代理類融合了原類和增強類,它可能與原類具有同樣的接口,也可能是原類的子類,所以當我們訪問原類的方法的時候,會先訪問增強類,再到原類。

好了,以上就說到這。

 

spring與springmvc整合出現AOP不起作用的原因:

1、spring與springmvc加載配置文件是不同步的,springmvc加載文件對注解進行掃描后,所有的注解都被掃到容器里面,當spring同樣加載配置文件掃描注解時,因為容器中已經

存在Service類,那么CGLib代理或jdk動態代理就不對它進行代理了,直接導致了applicationContext.xml中的事務不起作用,出現異常,事務不會滾。

2、解決方法:Spring MVC 和 Spring 整合的時候,SpringMVC的springmvc.xml文件中 配置掃描包,不要包含 service的注解,Spring的applicationContext.xml文件中 配置掃描包時,不要包含controller的注解,如下所示:
SpringMVC的xml配置:

	<!--1、 注解探測器,對注解進行掃描 -->
	<context:component-scan base-package="com">
		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
	</context:component-scan>

同樣的,spring的applicationContext.xml配置文件也一樣,不要掃描@Controller注解

	 <!-- 注解掃描器 -->
	 <context:component-scan base-package="com">
	 	<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
	 </context:component-scan>

 工作完成。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM