spring aop的5种通知类型都有
Before前置通知
AfterReturning后置通知
Around环绕通知
AfterThrowing异常通知
After最终通知
首先创建接口和实现类 先测试后置通知
package com.aaa.spring.dao; public interface UserService { public void insertUser(); public void updateUser(); public void deleteUser(); public void find(); }
package com.aaa.spring.dao.umpl; import com.aaa.spring.dao.UserService; import com.aaa.spring.exception.MyException; import org.springframework.stereotype.Component; @Component(创建userServiceImpl bean) public class UserServiceImpl implements UserService { @Override public void insertUser() { System.out.println("添加用户"); } @Override public void updateUser() { System.out.println("修改用户"); } @Override public void deleteUser() { System.out.println("删除用户"); } @Override public void find() { System.out.println("查询用户"); } }
创建要在执行的方法前后的类
package com.aaa.spring.advice; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.ExceptionHandler; @Component(获取bean对象) @Aspect(面向切面) public class LogAdvice { @AfterReturning("execution(void *User(..))")(后置通知(切入点)) public void log(JoinPoint jp){ (JoinPoint 连接点参数) String name=jp.getSignature().getName();(获取拦截的方法名) System.out.println(name+"执行之后记录成功"); } }
创建ApplicationContext文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org
/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework
.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework
.org/schema/aop/spring-aop.xsd"> <context:component-scan base-package="com.aaa.spring"></context:component-scan>(扫描创建bean的包就是加@Component的类的所有包) <aop:aspectj-autoproxy></aop:aspectj-autoproxy>(声明以注解的方式配置spring aop) </beans>
创建测试类
package com.aaa.spring.text; import com.aaa.spring.dao.UserService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Text { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("applicationcontext.xml");(获取主配置文件) UserService bean = (UserService)context.getBean("userServiceImpl");(获取实现类对象) bean.deleteUser(); System.out.println("*****************************"); bean.find(); System.out.println("*****************************"); bean.insertUser(); System.out.println("*****************************"); bean.updateUser(); } }
测试结果
五月 20, 2019 9:01:24 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@68de145: startup date [Mon May 20 21:01:24 CST 2019]; root of context hierarchy 五月 20, 2019 9:01:24 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [applicationcontext.xml] 删除用户 deleteUser执行之后记录成功 ***************************** 查询用户 ***************************** 添加用户 insertUser执行之后记录成功 ***************************** 修改用户 updateUser执行之后记录成功 Process finished with exit code 0
前置通知
只需要在LogAdvice 类里边再加方法
package com.aaa.spring.advice; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.ExceptionHandler; @Component @Aspect public class LogAdvice { @AfterReturning("execution(void *User(..))") public void log(JoinPoint jp){ String name=jp.getSignature().getName(); System.out.println(name+"执行之后记录成功"); } @Before("execution(void *User(..))") public void befor(JoinPoint jp){ String name=jp.getSignature().getName(); System.out.println(name+"执行之前记录成功"); } }
测试结果
五月 20, 2019 9:08:07 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@68de145: startup date [Mon May 20 21:08:07 CST 2019]; root of context hierarchy 五月 20, 2019 9:08:08 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [applicationcontext.xml] deleteUser执行之前记录成功 删除用户 deleteUser执行之后记录成功 ***************************** 查询用户 ***************************** insertUser执行之前记录成功 添加用户 insertUser执行之后记录成功 ***************************** updateUser执行之前记录成功 修改用户 updateUser执行之后记录成功 Process finished with exit code 0
环绕通知
只需要在LogAdvice 类里边再加方法
package com.aaa.spring.advice; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.ExceptionHandler; @Component @Aspect public class LogAdvice { @AfterReturning("execution(void *User(..))") public void log(JoinPoint jp){ String name=jp.getSignature().getName(); System.out.println(name+"执行之后记录成功"); } @Before("execution(void *User(..))") public void befor(JoinPoint jp){ String name=jp.getSignature().getName(); System.out.println(name+"执行之前记录成功"); } @Around("execution(void *User(..))") public void around(ProceedingJoinPoint pjp){ String name=pjp.getSignature().getName(); System.out.println(name+"环绕执行前"); try { pjp.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } System.out.println(name+"环绕后执行"); } }
测试结果
五月 20, 2019 9:10:12 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@68de145: startup date [Mon May 20 21:10:12 CST 2019]; root of context hierarchy 五月 20, 2019 9:10:12 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [applicationcontext.xml] deleteUser环绕执行前 deleteUser执行之前记录成功 删除用户 deleteUser环绕后执行 deleteUser执行之后记录成功 ***************************** 查询用户 ***************************** insertUser环绕执行前 insertUser执行之前记录成功 添加用户 insertUser环绕后执行 insertUser执行之后记录成功 ***************************** updateUser环绕执行前 updateUser执行之前记录成功 修改用户 updateUser环绕后执行 updateUser执行之后记录成功 Process finished with exit code 0
最终通知
只需要在LogAdvice 类里边再加方法
package com.aaa.spring.advice; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.ExceptionHandler; @Component @Aspect public class LogAdvice { @AfterReturning("execution(void *User(..))") public void log(JoinPoint jp){ String name=jp.getSignature().getName(); System.out.println(name+"执行之后记录成功"); } @Before("execution(void *User(..))") public void befor(JoinPoint jp){ String name=jp.getSignature().getName(); System.out.println(name+"执行之前记录成功"); } @Around("execution(void *User(..))") public void around(ProceedingJoinPoint pjp){ String name=pjp.getSignature().getName(); System.out.println(name+"环绕执行前"); try { pjp.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } System.out.println(name+"环绕后执行"); } @After("execution(void *User(..))") public void after(JoinPoint jp){ String name=jp.getSignature().getName(); System.out.println(name+"最终执行记录成功"); } }
测试结果
五月 20, 2019 9:12:00 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@68de145: startup date [Mon May 20 21:12:00 CST 2019]; root of context hierarchy 五月 20, 2019 9:12:00 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [applicationcontext.xml] deleteUser环绕执行前 deleteUser执行之前记录成功 删除用户 deleteUser环绕后执行 deleteUser最终执行记录成功 deleteUser执行之后记录成功 ***************************** 查询用户 ***************************** insertUser环绕执行前 insertUser执行之前记录成功 添加用户 insertUser环绕后执行 insertUser最终执行记录成功 insertUser执行之后记录成功 ***************************** updateUser环绕执行前 updateUser执行之前记录成功 修改用户 updateUser环绕后执行 updateUser最终执行记录成功 updateUser执行之后记录成功 Process finished with exit code 0
异常通知,这里我们自定义一个异常
先创建一个异常类继承RuntimeException程序异常
package com.aaa.spring.exception; public class MyException extends RuntimeException{ public MyException(String yc){ super(yc); } }
然后在LogAdvice 类里添加方法这里为了方便测试把上面的都加上了注释
package com.aaa.spring.advice; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.ExceptionHandler; @Component @Aspect public class LogAdvice { /* @AfterReturning("execution(void *User(..))") public void log(JoinPoint jp){ String name=jp.getSignature().getName(); System.out.println(name+"执行之后记录成功"); } @Before("execution(void *User(..))") public void befor(JoinPoint jp){ String name=jp.getSignature().getName(); System.out.println(name+"执行之前记录成功"); } @Around("execution(void *User(..))") public void around(ProceedingJoinPoint pjp){ String name=pjp.getSignature().getName(); System.out.println(name+"环绕执行前"); try { pjp.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } System.out.println(name+"环绕后执行"); } @After("execution(void *User(..))") public void after(JoinPoint jp){ String name=jp.getSignature().getName(); System.out.println(name+"最终执行记录成功"); }*/ @AfterThrowing(pointcut = "execution(void *User(..))") public void excaption(JoinPoint jp){ String name=jp.getSignature().getName(); System.out.println("执行"+name+"时发生异常"); } }
然后在实现类里抛出异常
package com.aaa.spring.dao.umpl; import com.aaa.spring.dao.UserService; import com.aaa.spring.exception.MyException; import org.springframework.stereotype.Component; @Component public class UserServiceImpl implements UserService { @Override public void insertUser() { if(true){ throw new MyException("自定义异常"); } System.out.println("添加用户"); } @Override public void updateUser() { System.out.println("修改用户"); } @Override public void deleteUser() { System.out.println("删除用户"); } @Override public void find() { System.out.println("查询用户"); } }
测试结果
五月 20, 2019 9:18:57 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@68de145: startup date [Mon May 20 21:18:57 CST 2019]; root of context hierarchy 五月 20, 2019 9:18:57 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [applicationcontext.xml] 删除用户 ***************************** 查询用户 ***************************** 执行insertUser时发生异常 Exception in thread "main" com.aaa.spring.exception.MyException: 自定义异常 at com.aaa.spring.dao.umpl.UserServiceImpl.insertUser(UserServiceImpl.java:12) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) at com.sun.proxy.$Proxy7.insertUser(Unknown Source) at com.aaa.spring.text.Text.main(Text.java:17) Process finished with exit code 1