1 解析
1.1 通知执行顺序
2 代码演练
1 解析
1.1 通知执行顺序
aop执行方式为:前置通知==>所要增强的方法==>后置通知==>最终通知
在出现异常时会进行:前置通知==>所要增强的方法==>异常通知==>最终通知
而用xml进行配置时,是按照我们写好的顺序进行动态组合完成,最终和后置通知是随着xml配置的前后顺序改变的,但是经过测试不会影响前置和所要增强的方法的顺序,但是会影响最终和后置通知的位置.
我认为利用环绕通知进行方法的增强(aop:around)是一个比较好的方式,不会出现顺序问题.
2 代码演练
2.1 前置通知和后置通知
业务类:
package com.imooc.aop.schema.advice.biz; public class AspectBiz { public void biz(){ System.out.println("MoocAspect biz"); } public void biz2(){ System.out.println("MoocAspect biz2"); } }
配置文件:
<?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" 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"> <bean id = "moocAspect" class = "com.imooc.aop.schema.advice.MoocAspect"></bean> <bean id = "AspectBiz" class = "com.imooc.aop.schema.advice.biz.AspectBiz"></bean> <aop:config> <aop:aspect id="moocAspectAOP" ref="moocAspect"> <!-- 声明切入点:从哪里开始执行 --> <!-- 执行com.imooc.aop.schema.advice.biz包下的所有Biz结尾的java类中的所有方法时 --> <aop:pointcut expression="execution(* com.imooc.aop.schema.advice.biz.*Biz.*(..))" id="moocPointCut"/> <aop:before method="before" pointcut-ref="moocPointCut"/> <aop:after-returning method="after" pointcut-ref="moocPointCut"/> </aop:aspect> </aop:config> </beans>
通知(名词)所在的类:
package com.imooc.aop.schema.advice; public class MoocAspect { public void before(){ System.out.println("before"); } public void after(){ System.out.println("after"); } }
测试类:
package com.imooc.test.aop; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.BlockJUnit4ClassRunner; import com.imooc.aop.schema.advice.biz.AspectBiz; import com.imooc.test.base.UnitTestBase; @RunWith(BlockJUnit4ClassRunner.class) public class TestAOPSchemaAdvice extends UnitTestBase { public TestAOPSchemaAdvice(){ super("classpath:spring-aop-schema-advice.xml"); } @Test public void testBiz(){ AspectBiz aBiz = super.getbean("AspectBiz"); aBiz.biz(); aBiz.biz2(); } }
打印结果:
四月 15, 2019 8:19:44 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@285855bd: startup date [Mon Apr 15 20:19:44 CST 2019]; root of context hierarchy 四月 15, 2019 8:19:44 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring-aop-schema-advice.xml] before MoocAspect biz after before MoocAspect biz2 after 四月 15, 2019 8:19:45 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose 信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@285855bd: startup date [Mon Apr 15 20:19:44 CST 2019]; root of context hierarchy
2.2 异常通知和最终通知
业务类:
package com.imooc.aop.schema.advice.biz; public class AspectBiz { public void biz(){ System.out.println("MoocAspect biz"); throw new RuntimeException(); } }
配置文件:
<?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" 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"> <bean id = "moocAspect" class = "com.imooc.aop.schema.advice.MoocAspect"></bean> <bean id = "AspectBiz" class = "com.imooc.aop.schema.advice.biz.AspectBiz"></bean> <aop:config> <aop:aspect id="moocAspectAOP" ref="moocAspect"> <!-- 声明切入点:从哪里开始执行 --> <!-- 执行com.imooc.aop.schema.advice.biz包下的所有Biz结尾的java类中的所有方法时 --> <aop:pointcut expression="execution(* com.imooc.aop.schema.advice.biz.*Biz.*(..))" id="moocPointCut"/> <aop:before method="before" pointcut-ref="moocPointCut"/> <aop:after-returning method="afterreturning" pointcut-ref="moocPointCut"/> <aop:after-throwing method="throwing" pointcut-ref="moocPointCut"/> <aop:after method="after" pointcut-ref="moocPointCut"/>
</aop:aspect> </aop:config> </beans>
通知所在类:
package com.imooc.aop.schema.advice; public class MoocAspect { public void before(){ System.out.println("before"); } public void afterreturning(){ System.out.println("after returning"); } public void throwing(){ System.out.println("throw"); } public void after(){ System.out.println("Say Love me"); } }
测试类:
package com.imooc.test.aop; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.BlockJUnit4ClassRunner; import com.imooc.aop.schema.advice.biz.AspectBiz; import com.imooc.test.base.UnitTestBase; @RunWith(BlockJUnit4ClassRunner.class) public class TestAOPSchemaAdvice extends UnitTestBase { public TestAOPSchemaAdvice(){ super("classpath:spring-aop-schema-advice.xml"); } @Test public void testBiz(){ AspectBiz aBiz = super.getbean("AspectBiz"); aBiz.biz(); } }
打印日志:
四月 16, 2019 7:18:45 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4b19b8ae: startup date [Tue Apr 16 07:18:45 CST 2019]; root of context hierarchy 四月 16, 2019 7:18:45 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring-aop-schema-advice.xml] before MoocAspect biz throw Say Love me 四月 16, 2019 7:18:46 上午 org.springframework.context.support.ClassPathXmlApplicationContext doClose 信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@4b19b8ae: startup date [Tue Apr 16 07:18:45 CST 2019]; root of context hierarchy