面向切面编程,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。可以不修改源码添加新的功能。
目录
AOP术语
切入点表达式
注解实现AOP操作
xml配置文件实现AOP操作
AOP术语
连接点:可以被增强的方法。
切入点:实际被增强的方法。
通知:实际增强的逻辑部分称为通知。
通知类型:前置通知、后置通知、环绕通知、异常通知、最终通知。
切面:把通知应用到切入点的过程。
切入点表达式设置对哪个类的哪个方法进行增强
语法结构: execution([权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]) )
//对Test1类当中的所有方法进行增强 execution(* com.aoptest.Test1.*(..)) //对Test类当中的某一个方法进行增强 execution(* com.aoptest.Test1.方法名(..)) //对aoptest包中的所有类的所有方法进行增强 execution(* com.aoptest.*.*(..)) 注解实现AOP操作首先创建被增强的类
package com.aoptest; import org.springframework.stereotype.Component; @Component public class Test1 { public void Show() { System.out.println("需要被增强的方法show"); } }然后创建用于增强的类
package com.aoptest; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Component @Aspect public class Test2 { //通用的切入点表达式 @Pointcut(value = "execution(* com.aoptest.Test1.*(..))") public void pointcut() { } //前置通知 @Before注解表示前置通知 @Before(value = "execution(* com.aoptest.Test1.*(..))")//可以写入切入点表达式,也可以像下面一样设置通用的表达式填入方法即可 public void before() { System.out.println("前置通知"); } //最终通知 @After(value = "pointcut()")//效果和上面一样 public void after() { System.out.println("最终通知"); } //后置通知(返回通知)有异常的时候不执行 @AfterReturning(value = "pointcut()") public void afterReturning() { System.out.println("后置通知"); } //异常通知 @AfterThrowing(value = "pointcut()") public void afterThrowing() { System.out.println("异常通知"); } //环绕通知 @Around(value = "pointcut()") public void Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕通知前"); proceedingJoinPoint.proceed(); System.out.println("环绕通知后"); } }在xml文件当中开启注解扫描和Aspect生成代理对象
<!--开启注解扫描--> <context:component-scan base-package="com.aoptest"></context:component-scan> <!--开启Aspect生成代理对象--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>测试方法
@Test public void testAop() { ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); Test1 test1 = context.getBean("test1", Test1.class); test1.Show(); }?输出结果
?当出现异常的时候,后置通知是不会执行的
如果有多个类都增强相同的方法,可以通过@Order注解来实现增强类的优先级设置。
//括号中的数字越小,优先级越高 @Order(1)?例如我们再增加一个增强类Test3,设置优先级为0
package com.aoptest; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Aspect @Order(0) public class Test3 { @Before(value = "execution(* com.aoptest.Test1.*(..))") public void before() { System.out.println("前置通知Test3"); } }输出结果
?可以发现,前置通知Test3是最先输出的。?
xml配置文件实现AOP操作创建被增强的类
package com.aopxml; public class Book { public void buy() { System.out.println("buy"); } }创建增强类
package com.aopxml; public class BookProxy { public void before() { System.out.println("前置通知"); } public void after() { System.out.println("最终通知"); } }xml配置文件配置
<!--创建类--> <bean id="bookProxy" class="com.aopxml.BookProxy"></bean> <bean id="book" class="com.aopxml.Book"></bean> <!--配置aop增强--> <aop:config> <!--切入点--> <aop:pointcut id="pc" expression="execution(* com.aopxml.Book.*(..))"/> <!--配置切面--> <aop:aspect ref="bookProxy"> <!--设置增强作用在具体的方法上--> <aop:before method="before" pointcut-ref="pc"></aop:before><!--将前置通知作用在上面设置的pc切入点--> <aop:before method="after" pointcut-ref="pc"></aop:before> </aop:aspect> </aop:config>测试方法
@Test public void testAop2() { ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml"); Book book = context.getBean("book", Book.class); book.buy(); }输出结果
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。 |
标签: #JAVA #Spring5之AOP #可以不修改源码添加新的功能 #切入点实际被增强的方法 #通知实际增强的逻辑部分称为通知