1 解析
1.1 通知:after和afterreturning的区别
1.2 @RunWith 是什么?
2 代码演练
2.1 注解方式配置通知的两种方式
2.2 异常通知
2.3 非异常通知
1 解析
1.1 通知:after和afterreturning的区别
a after 后置通知相当于finally的功能,无论是否发生异常,都会执行,而返回后通知afterReturning 则在发生异常后,不再执行。
b after 后置通知 不会有返回值,而afterReturning返回后通知,一般有返回值, 详细代码演练参考2.2
c 如果同时有after 和afterReturning,一般先执行after,后执行afterReturning 详细代码演练参考2.3
1.2 @RunWith 是什么?
@RunWith 是一个运行器 * *
@RunWith(JUnit4.class)就是指用JUnit4来运行 * *
@RunWith(Suite.class)的话就是一套测试集合 * *
@RunWith(Suite.class)的话就是一套测试集合 * *
@ContextConfiguration Spring整合JUnit4测试时,使用注解引入多个配置文件
2 代码演练
2.1 注解方式配置通知的两种方式(着重看切面类)
测试类:
package com.imooc.test.aop; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.BlockJUnit4ClassRunner; import com.imooc.aop.aspectj.biz.MoocBiz; import com.imooc.test.base.UnitTestBase; /** @RunWith 是一个运行器 * * @RunWith(JUnit4.class)就是指用JUnit4来运行 * *@RunWith(Suite.class)的话就是一套测试集合 * *@RunWith(Suite.class)的话就是一套测试集合 * *@ContextConfiguration Spring整合JUnit4测试时,使用注解引入多个配置文件 * * @author weijingli */ @RunWith(BlockJUnit4ClassRunner.class) public class TestAspectJ extends UnitTestBase{ public TestAspectJ() { super("classpath:spring-aop-aspectj.xml"); } @Test public void testAspectJ(){ MoocBiz mBiz = super.getbean("moocBiz"); mBiz.save("This is Test!"); } }
配置文件:
<?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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd 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" > <!-- 自己添加注意: 1 context:component-scan 扫描包,根据注解找到通知。 使用注解的时候,记得添加扫描包的功能 2 aop:aspectj-autoproxy 通过配置织入@Aspectj切面 -->
<context:component-scan base-package="com.imooc.aop.aspectj"/>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<bean id="moocBiz" class="com.imooc.aop.aspectj.biz.MoocBiz"></bean> </beans>
实体类:
package com.imooc.aop.aspectj.biz; import org.springframework.stereotype.Service; @Service public class MoocBiz { /** * 1 为什么 用 save方法 返回 String 类型? * * 答:为了方便After Or AfterReturning 通知 接收 返回值 * * 2 为什么接收String 参数? * * 答:只是为了方便测试,没有任何实际意义。 * @param arg * @return */ public String save(String arg){ System.out.println("MoocBiz save "+arg); return "Save Success!"; } }
切面类:
package com.imooc.aop.aspectj; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * 注解切面类 * 注:本页面主要功能是:整理各种通知的注解 * @author weijingli * */ @Component @Aspect public class MoocAspect { /** * 该处设置切入点,主要是用来匹配目标对象类 * * 执行com.imooc.aop.aspect.biz 包下的 以Biz结尾的类的所有方法 */ @Pointcut("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))") public void pointcut(){} /** * 执行com.imooc.aop.aspect.biz 包下的所有类的 所有方法 */ @Pointcut("within(com.imooc.aop.aspectj.biz.*)") public void bizPointcut(){} /** * 前置通知 样例1 */ @Before("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))") public void before(){ System.out.println("before1"); } /** * 前置通知 样例2 */ @Before("pointcut()") public void before2(){ System.out.println("before2"); } }
打印日志:
四月 27, 2019 4:23:00 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@53b5e629: startup date [Sat Apr 27 16:23:00 CST 2019]; root of context hierarchy 四月 27, 2019 4:23:00 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring-aop-aspectj.xml] 四月 27, 2019 4:23:00 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory registerBeanDefinition 信息: Overriding bean definition for bean 'moocBiz' with a different definition: replacing [Generic bean: class [com.imooc.aop.aspectj.biz.MoocBiz]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [F:\xiangmu3\Xin\FuQiang\Spring\ddwei-dao\target\classes\com\imooc\aop\aspectj\biz\MoocBiz.class]] with [Generic bean: class [com.imooc.aop.aspectj.biz.MoocBiz]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [spring-aop-aspectj.xml]] 四月 27, 2019 4:23:00 下午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init> 信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring before1 before2 MoocBiz save This is Test! 四月 27, 2019 4:23:01 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose 信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@53b5e629: startup date [Sat Apr 27 16:23:00 CST 2019]; root of context hierarchy
2.2 异常通知
实体类:
package com.imooc.aop.aspectj.biz; import org.springframework.stereotype.Service; @Service public class MoocBiz { /** * 1 为什么 用 save方法 返回 String 类型? * * 答:为了方便After Or AfterReturning 通知 接收 返回值 * * 2 为什么接收String 参数? * * 答:只是为了方便测试,没有任何实际意义。 * @param arg * @return */ public String save(String arg){ System.out.println("MoocBiz save "+arg); throw new RuntimeException("Save Failed!"); // return "Save Success!"; } }
切面类:
package com.imooc.aop.aspectj; 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; import org.springframework.stereotype.Component; /** * 注解切面类 * 注:本页面主要功能是:整理各种通知的注解 * @author weijingli * */ @Component @Aspect public class MoocAspect { /** * 该处设置切入点,主要是用来匹配目标对象类 * * 执行com.imooc.aop.aspect.biz 包下的 以Biz结尾的类的所有方法 */ @Pointcut("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))") public void pointcut(){} /** * 执行com.imooc.aop.aspect.biz 包下的所有类的 所有方法 */ @Pointcut("within(com.imooc.aop.aspectj.biz.*)") public void bizPointcut(){} /** * 前置通知 样例1 */ @Before("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))") public void before(){ System.out.println("before1"); } /** * AfterReturning 执行后通知,接收 目标对象返回的值 * @param reValue */ @AfterReturning(pointcut="pointcut()",returning="reValue") public void afterReturning(Object reValue){ System.out.println("AfterReturning: "+reValue); } /** * 后置通知 */ @After("pointcut()") public void after(){ System.out.println("after:"); } /** * 异常通知: * * 接收异常返回的信息 */ @AfterThrowing(pointcut="pointcut()",throwing="e") public void afterThrowing(RuntimeException e){ System.out.println("AfterThrowing: "+e.getMessage()); } /** * 前置通知 样例2 */ /*@Before("pointcut()") public void before2(){ System.out.println("before2"); }*/ }
打印日志:
四月 27, 2019 4:48:55 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@45a5049a: startup date [Sat Apr 27 16:48:55 CST 2019]; root of context hierarchy 四月 27, 2019 4:48:55 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring-aop-aspectj.xml] 四月 27, 2019 4:48:56 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory registerBeanDefinition 信息: Overriding bean definition for bean 'moocBiz' with a different definition: replacing [Generic bean: class [com.imooc.aop.aspectj.biz.MoocBiz]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [F:\xiangmu3\Xin\FuQiang\Spring\ddwei-dao\target\classes\com\imooc\aop\aspectj\biz\MoocBiz.class]] with [Generic bean: class [com.imooc.aop.aspectj.biz.MoocBiz]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [spring-aop-aspectj.xml]] 四月 27, 2019 4:48:56 下午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init> 信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring before1 MoocBiz save This is Test! after: AfterThrowing: Save Failed! 四月 27, 2019 4:48:56 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose 信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@45a5049a: startup date [Sat Apr 27 16:48:55 CST 2019]; root of context hierarchy
2.3 非异常通知
切面类:
package com.imooc.aop.aspectj; 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; import org.springframework.stereotype.Component; /** * 注解切面类 * 注:本页面主要功能是:整理各种通知的注解 * @author weijingli * */ @Component @Aspect public class MoocAspect { /** * 该处设置切入点,主要是用来匹配目标对象类 * * 执行com.imooc.aop.aspect.biz 包下的 以Biz结尾的类的所有方法 */ @Pointcut("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))") public void pointcut(){} /** * 执行com.imooc.aop.aspect.biz 包下的所有类的 所有方法 */ @Pointcut("within(com.imooc.aop.aspectj.biz.*)") public void bizPointcut(){} /** * 前置通知 样例1 */ @Before("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))") public void before(){ System.out.println("before1"); } /** * AfterReturning 执行后通知,接收 目标对象返回的值 * @param reValue */ @AfterReturning(pointcut="pointcut()",returning="reValue") public void afterReturning(Object reValue){ System.out.println("AfterReturning: "+reValue); } /** * 后置通知 相当于java语法中的finally */ @After("pointcut()") public void after(){ System.out.println("after:"); } /** * 异常通知: * * 接收异常返回的信息 */ @AfterThrowing(pointcut="pointcut()",throwing="e") public void afterThrowing(RuntimeException e){ System.out.println("AfterThrowing: "+e.getMessage()); } /** * 环绕通知: * @param pjp * @return * @throws Throwable */ @Around("pointcut()") public Object around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("around 1"); Object obj = pjp.proceed(); System.out.println("around 2"); System.out.println("around :"+obj); return obj; } /** * 前置通知 样例2 */ /*@Before("pointcut()") public void before2(){ System.out.println("before2"); }*/ }
打印日志:
四月 28, 2019 6:56:52 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5512ce48: startup date [Sun Apr 28 06:56:52 CST 2019]; root of context hierarchy 四月 28, 2019 6:56:52 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring-aop-aspectj.xml] 四月 28, 2019 6:56:52 上午 org.springframework.beans.factory.support.DefaultListableBeanFactory registerBeanDefinition 信息: Overriding bean definition for bean 'moocBiz' with a different definition: replacing [Generic bean: class [com.imooc.aop.aspectj.biz.MoocBiz]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [F:\xiangmu3\Xin\FuQiang\Spring\ddwei-dao\target\classes\com\imooc\aop\aspectj\biz\MoocBiz.class]] with [Generic bean: class [com.imooc.aop.aspectj.biz.MoocBiz]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [spring-aop-aspectj.xml]] 四月 28, 2019 6:56:52 上午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init> 信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
around 1
before1
MoocBiz save This is Test!
around 2
around :Save Success!
after:
AfterReturning: Save Success!
四月 28, 2019 6:56:53 上午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@5512ce48: startup date [Sun Apr 28 06:56:52 CST 2019]; root of context hierarchy