使用Spring的注解方式实现AOP的细节

PersonService.java

Java代码 复制代码
  1. package cn.itcast.service;   
  2.   
  3. public interface PersonService {   
  4.     public void save(String name);   
  5.     public void update(String name, Integer id);   
  6.     public String getPersonName(Integer id);   
  7. }   
  8. PersonServiceBean.java   
  9. package cn.itcast.service.impl;   
  10.   
  11. import cn.itcast.service.PersonService;   
  12.   
  13. public class PersonServiceBean implements PersonService {   
  14.   
  15.     public String getPersonName(Integer id) {   
  16.         return "xxx";   
  17.     }   
  18.   
  19.     public void save(String name) {   
  20.         System.out.println("我是save()方法");   
  21.     }   
  22.   
  23.     public void update(String name, Integer id) {   
  24.         System.out.println("我是update()方法");   
  25.     }   
  26.   
  27. }  
package cn.itcast.service;

public interface PersonService {
	public void save(String name);
	public void update(String name, Integer id);
	public String getPersonName(Integer id);
}
PersonServiceBean.java
package cn.itcast.service.impl;

import cn.itcast.service.PersonService;

public class PersonServiceBean implements PersonService {

	public String getPersonName(Integer id) {
		return "xxx";
	}

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

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

}


beans.xml

Xml代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xmlns:context="http://www.springframework.org/schema/context"  
  5.        xmlns:aop="http://www.springframework.org/schema/aop"  
  6.        xsi:schemaLocation="http://www.springframework.org/schema/beans   
  7.            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
  8.            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd   
  9.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">  
  10.         <aop:aspectj-autoproxy/>  
  11.         <!--   
  12.             打开配置项,这个配置项是对@Aspectj这个注解进行支持   
  13.             前面已经说过了,注解本身是不能干活的,注解之所以能干活是因为后面有处理器对其进行处理   
  14.             这个配置相当于为我们将要使用的@Aspectj注解提供了解析的功能   
  15.         -->  
  16.         <bean id="myInterceptor" class="cn.itcast.service.MyInterceptor"/>  
  17.         <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean>  
  18. </beans>  



  后置通知是在业务方法执行完才执行的。还有最终通知
MyInterceptor.java

Java代码 复制代码
  1. package cn.itcast.service;   
  2.   
  3. import org.aspectj.lang.annotation.After;   
  4. import org.aspectj.lang.annotation.AfterReturning;   
  5. import org.aspectj.lang.annotation.Aspect;   
  6. import org.aspectj.lang.annotation.Before;   
  7. import org.aspectj.lang.annotation.Pointcut;   
  8. /**  
  9.  * 切面  
  10.  */  
  11. @Aspect //用来指明这个类是一个切面   
  12. public class MyInterceptor {   
  13.     @Pointcut("execution (* cn.itcast.service.impl.PersonServiceBean.*(..))")   
  14.     //切入点的表达式写完了,接下来要为切入点定义一个名称,这个名称的定义有点怪怪的   
  15.     //采用的是方法定义的形式来定义它的名称的   
  16.     private void anyMethod() {}//声明一个切入点,anyMethod()就是切入点的名称,括号也带上   
  17.   
  18.     @Before("anyMethod()")  //里面应该填入切入点的名称   
  19.     public void doAccessCheck() {   
  20.         System.out.println("前置通知");   
  21.     }   
  22.   
  23.     @AfterReturning("anyMethod()")   
  24.     public void doAfterReturning() {   
  25.         System.out.println("后置通知");   
  26.     }   
  27.   
  28.     @After("anyMethod()")   
  29.     public void doAfter() {   
  30.         System.out.println("最终通知");   
  31.     }   
  32. }  
package cn.itcast.service;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**
 * 切面
 */
@Aspect //用来指明这个类是一个切面
public class MyInterceptor {
	@Pointcut("execution (* cn.itcast.service.impl.PersonServiceBean.*(..))")
	//切入点的表达式写完了,接下来要为切入点定义一个名称,这个名称的定义有点怪怪的
	//采用的是方法定义的形式来定义它的名称的
	private void anyMethod() {}//声明一个切入点,anyMethod()就是切入点的名称,括号也带上

	@Before("anyMethod()")  //里面应该填入切入点的名称
	public void doAccessCheck() {
		System.out.println("前置通知");
	}

	@AfterReturning("anyMethod()")
	public void doAfterReturning() {
		System.out.println("后置通知");
	}

	@After("anyMethod()")
	public void doAfter() {
		System.out.println("最终通知");
	}
}


SpringAOPTest.java

Java代码 复制代码
  1. package junit.test;   
  2.   
  3. import org.junit.BeforeClass;   
  4. import org.junit.Test;   
  5. import org.springframework.context.ApplicationContext;   
  6. import org.springframework.context.support.ClassPathXmlApplicationContext;   
  7.   
  8. import cn.itcast.service.PersonService;   
  9.   
  10. public class SpringAOPTest {   
  11.   
  12.     @BeforeClass  
  13.     public static void setUpBeforeClass() throws Exception {   
  14.     }   
  15.   
  16.     @Test public void interceptorTest(){   
  17.         ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");   
  18.         PersonService personService = (PersonService)cxt.getBean("personService");   
  19.         personService.save("xx");   
  20.     }   
  21. }  
package junit.test;

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

import cn.itcast.service.PersonService;

public class SpringAOPTest {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	@Test public void interceptorTest(){
		ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");
		PersonService personService = (PersonService)cxt.getBean("personService");
		personService.save("xx");
	}
}


运行单元测试代码,输出结果是:
前置通知
我是save()方法
后置通知
最终通知


现在还剩下两种通知,例外通知和环绕通知,例外通知在什么时候起效果呢?看下之前AOP的拦截代码,在JDKProxyFactory.java里面

Java代码 复制代码
  1. public Object invoke(Object proxy, Method method, Object[] args)   
  2.             throws Throwable {//环绕通知   
  3.         PersonServiceBean bean = (PersonServiceBean) this.targetObject;   
  4.         Object result = null;   
  5.         if(bean.getUser()!=null){   
  6.             //..... advice()-->前置通知   
  7.             try {   
  8.                 result = method.invoke(targetObject, args);   
  9.                 // afteradvice() -->后置通知   
  10.             } catch (RuntimeException e) {   
  11.                 //exceptionadvice()--> 例外通知   
  12.             }finally{   
  13.                 //finallyadvice(); -->最终通知   
  14.             }   
  15.         }   
  16.         return result;   
  17.     }  
public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {//环绕通知
		PersonServiceBean bean = (PersonServiceBean) this.targetObject;
		Object result = null;
		if(bean.getUser()!=null){
			//..... advice()-->前置通知
			try {
				result = method.invoke(targetObject, args);
				// afteradvice() -->后置通知
			} catch (RuntimeException e) {
				//exceptionadvice()--> 例外通知
			}finally{
				//finallyadvice(); -->最终通知
			}
		}
		return result;
	}


可以看到,例外通知是在业务方法出现例外时执行的通知。它执行的时机是在捕获到例外之后,定义一个例外通知
MyInterceptor.java

Java代码 复制代码
  1. package cn.itcast.service;   
  2.   
  3. import org.aspectj.lang.annotation.After;   
  4. import org.aspectj.lang.annotation.AfterReturning;   
  5. import org.aspectj.lang.annotation.AfterThrowing;   
  6. import org.aspectj.lang.annotation.Aspect;   
  7. import org.aspectj.lang.annotation.Before;   
  8. import org.aspectj.lang.annotation.Pointcut;   
  9. /**  
  10.  * 切面  
  11.  */  
  12. @Aspect //用来指明这个类是一个切面   
  13. public class MyInterceptor {   
  14.     @Pointcut("execution (* cn.itcast.service.impl.PersonServiceBean.*(..))")   
  15.     //切入点的表达式写完了,接下来要为切入点定义一个名称,这个名称的定义有点怪怪的   
  16.     //采用的是方法定义的形式来定义它的名称的   
  17.     private void anyMethod() {}//声明一个切入点,anyMethod()就是切入点的名称,括号也带上   
  18.   
  19.     @Before("anyMethod()")  //里面应该填入切入点的名称   
  20.     public void doAccessCheck() {   
  21.         System.out.println("前置通知");   
  22.     }   
  23.   
  24.     @AfterReturning("anyMethod()")   
  25.     public void doAfterReturning() {   
  26.         System.out.println("后置通知");   
  27.     }   
  28.   
  29.     @After("anyMethod()")   
  30.     public void doAfter() {   
  31.         System.out.println("最终通知");   
  32.     }   
  33.        
  34.     @AfterThrowing("anyMethod()")   
  35.     public void doAfterThrowing() {   
  36.         System.out.println("例外通知");   
  37.     }   
  38.        
  39. }  
package cn.itcast.service;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**
 * 切面
 */
@Aspect //用来指明这个类是一个切面
public class MyInterceptor {
	@Pointcut("execution (* cn.itcast.service.impl.PersonServiceBean.*(..))")
	//切入点的表达式写完了,接下来要为切入点定义一个名称,这个名称的定义有点怪怪的
	//采用的是方法定义的形式来定义它的名称的
	private void anyMethod() {}//声明一个切入点,anyMethod()就是切入点的名称,括号也带上

	@Before("anyMethod()")  //里面应该填入切入点的名称
	public void doAccessCheck() {
		System.out.println("前置通知");
	}

	@AfterReturning("anyMethod()")
	public void doAfterReturning() {
		System.out.println("后置通知");
	}

	@After("anyMethod()")
	public void doAfter() {
		System.out.println("最终通知");
	}
	
	@AfterThrowing("anyMethod()")
	public void doAfterThrowing() {
		System.out.println("例外通知");
	}
	
}


要应用例外通知的话,业务bean要做一下手脚

PersonServiceBean.java

Java代码 复制代码
  1. package cn.itcast.service.impl;   
  2.   
  3. import cn.itcast.service.PersonService;   
  4.   
  5. public class PersonServiceBean implements PersonService {   
  6.   
  7.     public String getPersonName(Integer id) {   
  8.         return "xxx";   
  9.     }   
  10.   
  11.     public void save(String name) {   
  12.         throw new RuntimeException("我爱例外。。");   
  13.         //System.out.println("我是save()方法");   
  14.     }   
  15.   
  16.     public void update(String name, Integer id) {   
  17.         System.out.println("我是update()方法");   
  18.     }   
  19.   
  20. }  
package cn.itcast.service.impl;

import cn.itcast.service.PersonService;

public class PersonServiceBean implements PersonService {

	public String getPersonName(Integer id) {
		return "xxx";
	}

	public void save(String name) {
		throw new RuntimeException("我爱例外。。");
		//System.out.println("我是save()方法");
	}

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

}



如果出现例外的话,后置通知是不会执行的;不管出不出例外,最终通知必然会执行
运行单元测试代码,控制台输出:
前置通知
最终通知
例外通知

在JUnit里面,出现了例外
java.lang.RuntimeException: 我爱例外。。
at cn.itcast.service.impl.PersonServiceBean.save(PersonServiceBean.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
.............................................
我的疑问:为什么例外通知会在最终通知后面的呢?不明白!

把例外注释掉,恢复原型
PersonServiceBean.java

Java代码 复制代码
  1. package cn.itcast.service.impl;   
  2.   
  3. import cn.itcast.service.PersonService;   
  4.   
  5. public class PersonServiceBean implements PersonService {   
  6.   
  7.     public String getPersonName(Integer id) {   
  8.             System.out.println("我是getPersonName()方法");      
  9.         return "xxx";   
  10.     }   
  11.   
  12.     public void save(String name) {   
  13.         //throw new RuntimeException("我爱例外。。");   
  14.         System.out.println("我是save()方法");   
  15.     }   
  16.   
  17.     public void update(String name, Integer id) {   
  18.         System.out.println("我是update()方法");   
  19.     }   
  20.   
  21. }  
package cn.itcast.service.impl;

import cn.itcast.service.PersonService;

public class PersonServiceBean implements PersonService {

	public String getPersonName(Integer id) {
            System.out.println("我是getPersonName()方法");   
		return "xxx";
	}

	public void save(String name) {
		//throw new RuntimeException("我爱例外。。");
		System.out.println("我是save()方法");
	}

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

}


然后学习最后一种通知,环绕通知。 其实Struts2里面提供的拦截器,就是属于环绕通知。环绕通知在我们做权限的时候,被大量使用到
先看下环绕通知的定义:

Java代码 复制代码
  1. @Around("anyMethod()")//环绕通知   
  2. public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {   
  3.     return pjp.proceed();   
  4. }  
@Around("anyMethod()")//环绕通知
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
    return pjp.proceed();
}

这方法需要有一个输入参数ProceedingJoinPoint pjp,这输入参数是固定的形式,固定的写法。
注意:如果使用了环绕通知的话,必须确保在环绕通知内部执行return pjp.proceed();这个方法,如果不执行这个方法的话,那么业务bean中被拦截的方法是不会执行的。当然在执行这个方法的时候,如果后面还有切面的话,它的执行顺序应该是这样的,先执行后面的切面,如果后面没有切面的话,再执行最终目标对象的业务方法。如果不调用pjp.proceed();这个方法,那么后面的切面及业务bean的方法都不会被执行,所以在这里就要小心了。
MyInterceptor.java

Java代码 复制代码
  1. package cn.itcast.service;   
  2.   
  3. import org.aspectj.lang.ProceedingJoinPoint;   
  4. import org.aspectj.lang.annotation.After;   
  5. import org.aspectj.lang.annotation.AfterReturning;   
  6. import org.aspectj.lang.annotation.AfterThrowing;   
  7. import org.aspectj.lang.annotation.Around;   
  8. import org.aspectj.lang.annotation.Aspect;   
  9. import org.aspectj.lang.annotation.Before;   
  10. import org.aspectj.lang.annotation.Pointcut;   
  11. /**  
  12.  * 切面  
  13.  */  
  14. @Aspect //用来指明这个类是一个切面   
  15. public class MyInterceptor {   
  16.     @Pointcut("execution (* cn.itcast.service.impl.PersonServiceBean.*(..))")   
  17.     //切入点的表达式写完了,接下来要为切入点定义一个名称,这个名称的定义有点怪怪的   
  18.     //采用的是方法定义的形式来定义它的名称的   
  19.     private void anyMethod() {}//声明一个切入点,anyMethod()就是切入点的名称,括号也带上   
  20.   
  21.     @Before("anyMethod()")  //里面应该填入切入点的名称   
  22.     public void doAccessCheck() {   
  23.         System.out.println("前置通知");   
  24.     }   
  25.   
  26.     @AfterReturning("anyMethod()")   
  27.     public void doAfterReturning() {   
  28.         System.out.println("后置通知");   
  29.     }   
  30.   
  31.     @After("anyMethod()")   
  32.     public void doAfter() {   
  33.         System.out.println("最终通知");   
  34.     }   
  35.   
  36.     @AfterThrowing("anyMethod()")   
  37.     public void doAfterThrowing() {   
  38.         System.out.println("例外通知");   
  39.     }   
  40.   
  41.     @Around("anyMethod()")//环绕通知   
  42.     public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {   
  43.         //if(){ 这种应用场合下,特别适合做权限的,因为这里可以判断用户是否有权限   
  44.         System.out.println("进入方法");   
  45.         Object result = pjp.proceed();   
  46.         System.out.println("退出方法");   
  47.         //}   
  48.         return result;   
  49.     }   
  50.   
  51. }  
package cn.itcast.service;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**
 * 切面
 */
@Aspect //用来指明这个类是一个切面
public class MyInterceptor {
	@Pointcut("execution (* cn.itcast.service.impl.PersonServiceBean.*(..))")
	//切入点的表达式写完了,接下来要为切入点定义一个名称,这个名称的定义有点怪怪的
	//采用的是方法定义的形式来定义它的名称的
	private void anyMethod() {}//声明一个切入点,anyMethod()就是切入点的名称,括号也带上

	@Before("anyMethod()")  //里面应该填入切入点的名称
	public void doAccessCheck() {
		System.out.println("前置通知");
	}

	@AfterReturning("anyMethod()")
	public void doAfterReturning() {
		System.out.println("后置通知");
	}

	@After("anyMethod()")
	public void doAfter() {
		System.out.println("最终通知");
	}

	@AfterThrowing("anyMethod()")
	public void doAfterThrowing() {
		System.out.println("例外通知");
	}

	@Around("anyMethod()")//环绕通知
	public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
		//if(){ 这种应用场合下,特别适合做权限的,因为这里可以判断用户是否有权限
		System.out.println("进入方法");
		Object result = pjp.proceed();
		System.out.println("退出方法");
		//}
		return result;
	}

}


实际上,如果我们使用环绕通知的话,前面的前置通知,后置通知,例外通知,最终通知都可以实现,都可以人工去实现它.
因为我们完全可以在Object result = pjp.proceed();前执行前置通知的方法,在这句后执行后置的代码,出现例外的时候再执行例外通知的方法。。使用环绕通知完全可以实现这几种功能,而没必要再使用这几种通知类型。

看下环绕通知的应用是否能够成功,运行单元测试代码,控制台输出
前置通知
进入方法
我是save()方法
后置通知
最终通知
退出方法


成功。这里已经给大家介绍完了怎样去定义切面,定义切入点,怎样应用各种类型的通知。 这里,肯定会有一些同学想到一些问题:如果我需要得到输入参数的情况下,怎么办呢?好比在前置通知里面,我需要得到用户输入的数据,可以采用这种写法:

Java代码 复制代码
  1. @Before("anyMethod() && args(n)")   
  2.     /*  
  3.       两个条件一合成,代表执行cn.itcast.service.impl.PersonServiceBean这个类里面的所有方法,  
  4.       并且要求方法里面的参数只有一个,而且是String类型  
  5.      */  
  6.     public void doAccessCheck(String n) {   
  7.         System.out.println("前置通知:" + n);   
  8.     }  
@Before("anyMethod() && args(n)")
	/*
	  两个条件一合成,代表执行cn.itcast.service.impl.PersonServiceBean这个类里面的所有方法,
	  并且要求方法里面的参数只有一个,而且是String类型
	 */
	public void doAccessCheck(String n) {
		System.out.println("前置通知:" + n);
	}


现在呢,这个前置通知只针对PersonServiceBean.java里面的save(String name)方法,getPersonName(Integer id)方法和update(String name, Integer id)方法对前置通知而言,它都不会被拦截到。
执行单元测试代码,控制台输出:
前置通知:xx
进入方法
我是save()方法
后置通知
最终通知
退出方法

看到,前置通知把xxx打印出来了,xxx是输入参数n,说明我们获取到输入参数了

有同学还会问:我要获取返回结果,那该怎么办呢?  比如,要获得getPersonName(Integer id)的返回结果,那该怎么办呢?
代码应该这样写:

Java代码 复制代码
  1. @AfterReturning(pointcut="anyMethod()", returning="rsl")   
  2. public void doAfterReturning(String rsl) {   
  3.     System.out.println("后置通知:" + rsl);   
  4. }  
@AfterReturning(pointcut="anyMethod()", returning="rsl")
public void doAfterReturning(String rsl) {
    System.out.println("后置通知:" + rsl);
}

这样使用的话,就相当于在"execution (* cn.itcast.service.impl.PersonServiceBean.*(..))"这里的第一个*号,申明返回类型是String,如果使用了returning属性,会把返回结果作为输入参数传给doAfterReturning方法.
客户端代码更换一下,
SpringAOPTest.java

Java代码 复制代码
  1. package junit.test;   
  2.   
  3. import org.junit.BeforeClass;   
  4. import org.junit.Test;   
  5. import org.springframework.context.ApplicationContext;   
  6. import org.springframework.context.support.ClassPathXmlApplicationContext;   
  7.   
  8. import cn.itcast.service.PersonService;   
  9.   
  10. public class SpringAOPTest {   
  11.   
  12.     @BeforeClass  
  13.     public static void setUpBeforeClass() throws Exception {   
  14.     }   
  15.   
  16.     @Test public void interceptorTest(){   
  17.         ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");   
  18.         PersonService personService = (PersonService)cxt.getBean("personService");   
  19.         personService.getPersonName(2);   
  20.     }   
  21. }  
package junit.test;

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

import cn.itcast.service.PersonService;

public class SpringAOPTest {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	@Test public void interceptorTest(){
		ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");
		PersonService personService = (PersonService)cxt.getBean("personService");
		personService.getPersonName(2);
	}
}


运行单元测试代码,控制台输出:
进入方法
我是getPersonName()方法
后置通知:xxx
最终通知
退出方法


证明,返回结果我们是得到了。

有同学还会问:在出现例外的时候,能不能得到业务方法抛出的例外呢?也是可以的。可以这样做:

Java代码 复制代码
  1. @AfterThrowing(pointcut="anyMethod()", throwing="e")   
  2.     public void doAfterThrowing(Exception e) {   
  3.         System.out.println("例外通知:" + e);   
  4.     }  
@AfterThrowing(pointcut="anyMethod()", throwing="e")
	public void doAfterThrowing(Exception e) {
		System.out.println("例外通知:" + e);
	}



把例外抛出:
PersonServiceBean.java

Java代码 复制代码
  1. package cn.itcast.service.impl;   
  2.   
  3. import cn.itcast.service.PersonService;   
  4.   
  5. public class PersonServiceBean implements PersonService {   
  6.   
  7.     public String getPersonName(Integer id) {   
  8.         System.out.println("我是getPersonName()方法");   
  9.         return "xxx";   
  10.     }   
  11.   
  12.     public void save(String name) {   
  13.         throw new RuntimeException("我爱例外。。");   
  14.         //System.out.println("我是save()方法");   
  15.     }   
  16.   
  17.     public void update(String name, Integer id) {   
  18.         System.out.println("我是update()方法");   
  19.     }   
  20.   
  21. }  
package cn.itcast.service.impl;

import cn.itcast.service.PersonService;

public class PersonServiceBean implements PersonService {

	public String getPersonName(Integer id) {
		System.out.println("我是getPersonName()方法");
		return "xxx";
	}

	public void save(String name) {
		throw new RuntimeException("我爱例外。。");
		//System.out.println("我是save()方法");
	}

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

}


SpringAOPTest.java

Java代码 复制代码
  1. package junit.test;   
  2.   
  3. import org.junit.BeforeClass;   
  4. import org.junit.Test;   
  5. import org.springframework.context.ApplicationContext;   
  6. import org.springframework.context.support.ClassPathXmlApplicationContext;   
  7.   
  8. import cn.itcast.service.PersonService;   
  9.   
  10. public class SpringAOPTest {   
  11.   
  12.     @BeforeClass  
  13.     public static void setUpBeforeClass() throws Exception {   
  14.     }   
  15.   
  16.     @Test public void interceptorTest(){   
  17.         ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");   
  18.         PersonService personService = (PersonService)cxt.getBean("personService");   
  19.         personService.save("tertret");   
  20.     }   
  21. }  
package junit.test;

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

import cn.itcast.service.PersonService;

public class SpringAOPTest {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	@Test public void interceptorTest(){
		ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");
		PersonService personService = (PersonService)cxt.getBean("personService");
		personService.save("tertret");
	}
}


运行单元测试代码,控制台输出:
前置通知:tertret
进入方法
最终通知
例外通知:java.lang.RuntimeException: 我爱例外。。

可以看到,例外是得到了。

这些就是我们在开发时,怎样得到输入参数,返回结果,抛出的异常,通过这些方式我们都可以得到。

基于注解的方式使用切面,已经给大家介绍完了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值