AOP_使用spring框架進行面向切面程式設計
阿新 • • 發佈:2019-02-12
用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容器管理
需要注意切入點執行的方法的引數