1. 程式人生 > >AOP_使用spring框架進行面向切面程式設計

AOP_使用spring框架進行面向切面程式設計

用spring實現AOP有兩種方式:基於xml配置方式和基於註解方式,

基於註解方式

一、架包:cglib-nodep-2.1_3.jar  aspectjweaver.jar  aspectjrt.jar(AOP)

      其它架包:common-annotations.jar   spring.jar    commons-logging.jar

二、先在配置檔案中加入如下內容

<?xml version="1.0" encoding="UTF-8"?>
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
</beans>

三、啟動對 aspectj 的支援,在xml檔案中加入如下內容

<aop:aspectj-autoproxy />

四、編寫核心程式碼

    PersonService.java

package com.qh.service;

public interface PersonService {
	public void save(String name);

	public void update(String name);
}

    PersonServiceImp.java

package com.qh.serviceImp;

import com.qh.service.PersonService;

public class PersonServiceImp implements PersonService {

	public void save(String name) {
		System.out.println("我是save()方法!"+name);
	}

	public void update(String name) {
		System.out.println("我是update()方法!");
	}

}

    MyInterceptor.java

package com.qh.service;
/*
 * 切面的實現
 */
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
//指明該類為一個切面
@Aspect
public class MyInterceptor {
	/*定義切入點,攔截方法
	 *使用AOP表述是語言:執行(返回值型別  要攔截的包  子包  類.方法(任意引數))
	 *該句解釋:執行 com.qh.service及其子包中的所有類的所有帶任意引數的方法,並返回任意型別值
	 */
	@Pointcut("execution(* com.qh.service..*.*(..))")
	private void anyMethod(){}//宣告一個切入點名稱anyMethod()
	@Before("anyMethod()")//定義前置通知,當然還有其它通知
	public void doprint(){
		System.out.println("執行!");
	}
} 
//其它通知      
	//只攔截包含一個引數的方法,並將該引數傳給doBefore()方法
	@Before("anyMethod()&&args(str)")
	public void doBefore(String str){
		System.out.println("我是前置通知!"+str);
	}
	//定義後置通知,將攔截的方法的返回結果作為doAfterReturning()方法的引數
	@AfterReturning(pointcut="anyMethod()",returning="str")
	public void doAfterReturning(String str){
		System.out.println("我是後置通知!"+str);
	}
	//定義例外通知,將異常資訊作為doAfterThrowing()方法的引數
	@AfterThrowing(pointcut="anyMethod()",throwing="e")
	public void doAfterThrowing(Exception e){
		System.out.println("我是例外通知!"+e);
	}
	@After("anyMethod()")//定義最終通知
	public void doAfter(){
		System.out.println("我是最終通知!");
	}
	@Around("anyMethod()")//定義環繞通知,此方法適合做許可權控制
	//此方法格式固定
	public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("我是環繞通知!進入方法");
		//if(){
		Object object=pjp.proceed();//一定要執行的方法,假如不執行該方法,被攔截的方法是不會執行的
		//}
		System.out.println("我是環繞通知!退出方法");
		return object;
	}

五、將PersonServiceImp和MyInterceptor類交給spring容器  

<bean id="personServiceImp" class="com.qh.serviceImp.PersonServiceImp"></bean>
<bean id="myInterceptor" class="com.qh.service.MyInterceptor"></bean>

六、編寫測試程式碼:InterceptorTest.java

package com.qh.test;

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

import com.qh.service.PersonService;

public class InterceptorTest {

	@Test
	public void test() {
		ApplicationContext apx=new ClassPathXmlApplicationContext("beans.xml");
		PersonService personService=(PersonService) apx.getBean("personServiceImp");
		personService.save("xionggui");
	}

}

 七、結果

      執行!
      我是save()方法!xionggui

 八、小結(針對本例)

     例外通知出現在Junit的控制檯中、環繞通知多用於許可權控制

基於xml配置方式

一、架包和第一種方式一樣

二、xml檔案

<aop:config><!-- aop配置 -->
<aop:aspect id="aopCut" ref="myInterceptor"><!-- 引用切面 -->
<!-- 可以定義多個切入點 -->
<aop:pointcut expression="execution(* com.qh.service..*.*(..)) and args(str)" id="myPointcut"/>
<aop:pointcut expression="execution(* com.qh.service..*.*(..))" id="myPointcut2"/>
<aop:before method="doBeforeOne" pointcut-ref="myPointcut2" />
<aop:before method="doBefore" pointcut-ref="myPointcut" arg-names="str"/>
<aop:after-returning method="doAfterReturning" pointcut-ref="myPointcut" arg-names="str"/>
<!-- aop:after-throwing method="doAfterThrowing"  pointcut-ref="myPointcut"/-->
<aop:after method="doAfter" pointcut-ref="myPointcut2"/>
<aop:around method="doAround" pointcut-ref="myPointcut2"/>
</aop:aspect>
</aop:config>

三、PersonServiceImp.java

package com.qh.service;
/*
 * 切面的實現
 */
import org.aspectj.lang.ProceedingJoinPoint;
public class MyInterceptor {
	
	public void doBeforeOne(){
		System.out.println("我是第一個前置通知!");
	}
	public void doBefore(String str){
		System.out.println("我是前置通知!"+str);
	}
	public void doAfterReturning(String str){
		System.out.println("我是後置通知!"+str);
	}
	public void doAfterThrowing(Exception e){
		System.out.println("我是例外通知!"+e);
	}
	public void doAfter(){
		System.out.println("我是最終通知!");
	}
	public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("我是環繞通知!進入方法");
		//if(){
			Object object=pjp.proceed();//一定要執行的方法,假如不執行該方法,被攔截的方法是不會執行的
		//}
		System.out.println("我是環繞通知!退出方法");
		return object;
	}
}

    其它程式碼和第一種方法一樣。

四、注意

    要將上面2個類交給spring容器管理

    需要注意切入點執行的方法的引數