1、修改 MyInterceptor 类,代码如下:
package org.learn.spring.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 {
//定义要拦截的方法,拦截 personServiceImpl 类下所有方法的执行
/**
* 第一个 * 表示 方法的返回值类型,* 表示任意类型
* org.learn.spring.service.impl.personServiceImpl 表示包下的类, 也可以写成 org.learn.spring.service 这样表示该包下所有的类,以及子包中的类
* 第二个 * 表示方法名称,这里表示是任意的方法,后接括号中的两点是表示参数是任意的,不管参数的个数和参数类型
*/
@Pointcut("execution(* org.learn.spring.service.impl.personServiceImpl.*(..))")
private void anyMethod() {}//声明一个切入点
@Before("anyMethod()")//定义前置通知
public void doAccessCheck() {
System.out.println("前置通知");
}
@AfterReturning("anyMethod()")//定义后置通知
public void doAfterReturning() {
System.out.println("后置通知");
}
@AfterThrowing("anyMethod()")//定义例外通知
public void doAfterThrowing() {
System.out.println("例外通知");
}
@After("anyMethod()")//定义最终通知
public void doAfter() {
System.out.println("最终通知");
}
@Around("anyMethod()")//定义环绕通知
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("进入方法");
Object reuslt = pjp.proceed();
System.out.println("退出方法");
return reuslt;
}
}
如果要想执行例外通知,则要在调用的方法上抛出异常。如下代码所示:
package org.learn.spring.service.impl;
import javax.management.RuntimeErrorException;
import org.learn.spring.service.personService;
public class personServiceImpl implements personService {
@Override
public void save(String name) {
System.out.println("save()方法");
}
@Override
public void update(String name, Integer id) {
//throw new RuntimeErrorException("例外通知");
System.out.println("update()方法");
}
@Override
public String getPersonServiceName(Integer id) {
System.out.print("getPersonServiceName()方法");
return "xxx";
}
}
将屏蔽的异常释放即可。
(2) 如果要想得到方法传入的参数值,即可如下:
args(name) 的 name 和 doAccessCheck(String name)参数名要一致 , 传入的参数类型是 String 类型,并且只有一个参数,由此也可以判断拦截的方法是哪一个
@Before("anyMethod() && args(name)")//定义前置通知
public void doAccessCheck(String name) {
System.out.println("前置通知:"+name);
}
(3) 获取方法的返回值,如下:
pointcut 切入点,returning 返回参数
@AfterReturning(pointcut="anyMethod()",returning="revalue")//定义后置通知
public void doAfterReturning(String revalue) {
System.out.println("后置通知:"+revalue);
}
(4) 得到方法抛出的异常,如下:
pointcut 切入点,throwing 抛出异常
@AfterThrowing(pointcut="anyMethod()", throwing="ex")//定义例外通知
public void doAfterThrowing(Exception ex) {
System.out.println("例外通知:"+ex);
}
(5) 详细如下:
package org.learn.spring.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 {
//定义要拦截的方法,拦截 personServiceImpl 类下所有方法的执行
/**
* 第一个 * 表示 方法的返回值类型,* 表示任意类型
* org.learn.spring.service.impl.personServiceImpl 表示包下的类, 也可以写成 org.learn.spring.service 这样表示该包下所有的类,以及子包中的类
* 第二个 * 表示方法名称,这里表示是任意的方法,后接括号中的两点是表示参数是任意的,不管参数的个数和参数类型
*/
@Pointcut("execution(* org.learn.spring.service.impl.personServiceImpl.*(..))")
private void anyMethod() {}//声明一个切入点
//传入的参数类型是 String 类型,并且只有一个参数,由此也可以判断拦截的方法是哪一个
//args(name) 的 name 和 doAccessCheck(String name)参数名要一致
@Before("anyMethod() && args(name)")//定义前置通知
public void doAccessCheck(String name) {
System.out.println("前置通知:"+name);
}
// pointcut 切入点,returning 返回参数
@AfterReturning(pointcut="anyMethod()",returning="revalue")//定义后置通知
public void doAfterReturning(String revalue) {
System.out.println("后置通知:"+revalue);
}
// pointcut 切入点,throwing 抛出异常
@AfterThrowing(pointcut="anyMethod()", throwing="ex")//定义例外通知
public void doAfterThrowing(Exception ex) {
System.out.println("例外通知:"+ex);
}
@After("anyMethod()")//定义最终通知
public void doAfter() {
System.out.println("最终通知");
}
@Around("anyMethod()")//定义环绕通知
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("进入方法");
Object reuslt = pjp.proceed();
System.out.println("退出方法");
return reuslt;
}
}
(6) 要得到想要的结果,测试类中调用的方法也在改变:
package org.learn.spring.test;
import org.junit.Test;
import org.learn.spring.service.personService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class personTest {
@Test
public void test() {
//实例化spring容器
ApplicationContext cxt = new ClassPathXmlApplicationContext("learn1.xml");
personService service = (personService)cxt.getBean("personService");
service.save("xxx");
service.getPersonServiceName(1);
service.update("dddd", 3);
}
}
(7) personServiceImpl 类中的 update 方法要做改变:
@Override
public void update(String name, Integer id) {
throw new RuntimeException("例外通知");
//System.out.println("update()方法");
}