Spring AOP(前置通知方法 、后置通知方法 、环绕通知方法 )与拦截器的使用

绝地灬酷狼 2022-01-21 11:33 843阅读 0赞

AOP(Aspect Oriented Programming)也就是面向切面编程的技术。AOP基于IoC基础,是对OOP的有益补充。AOP是代码之间解耦的一 种实现。可以这样理解,面向对象编程是从静态角度考虑程序结构,面向切面编程是从动态角度考虑程序运行过程。AOP将应用系统分为两部分:
(1)核心业务逻辑(Core Business Concerns)。
(2)横向的通用逻辑,也就是所谓的切面(Crosscutting Enterprise Concerns)。
例如,所有大中型应用都要涉及的持久化管理(Persistent)、事务管理(Transaction Management)、安全管理(Security)、日志管理(Logging)和调试管理(Debugging)等。

AOP的底层实现原理实际是Java语言的动态代理机制。AOP 代理是由AOP框架动态生成一个对象,该对象可作为目标对象使用。AOP代理包含了目标对象的全部方法,但代理中的方法与目标对象的方法存在差异: AOP方法在特定切入点添加了增强处理,并回调了目标对象的方法。Spring 的AOP通常和IoC配合使用,需要程序员参与的有3个部分:
(1)定义普通业务组件。
(2)定义切入点。一个切入点可以横切多个业务组件。
(3)定义增强处理。增强处理就是在AOP框架为普通业务组件织入的处理动作。
Spring有如下两种方式来定义切入点和增强处理:
(1)annotation 配置方式。使用@Aspect、 @Pointcut 等Annotation标注切入点和增强处理。
(2)xml 配置方式。使用xml配置文件定义切入点和增强处理。


我使用的是上一个学习crud操作的代码(MVC),稍作修改完成这个知识点的学习。
使用Spring实现mysql数据库的CRUD操作

①AOP的前置通知方法 、后置通知方法 、环绕通知方法

首先导入相关的包:
在这里插入图片描述

(1)定义一个java文件来使用AOP技术。(LogAdvice.java(日志通知切面))

LogAdvice.java

  1. package com.advice;
  2. import org.aspectj.lang.JoinPoint;
  3. import org.aspectj.lang.ProceedingJoinPoint;
  4. public class LogAdvice {
  5. //前置通知方法
  6. public void myBeforeAdvice(JoinPoint joinPoint){
  7. String methodname = joinPoint.getSignature().getName();
  8. System.out.println("Before前置通知——执行"+methodname+"方法前");
  9. }
  10. //后置通知方法
  11. public void myAfterAdvice(JoinPoint joinPoint){
  12. String methodname = joinPoint.getSignature().getName();
  13. System.out.println("执行"+methodname+"方法后——After后置通知");
  14. }
  15. //环绕通知方法
  16. public void myAroundAdvice(ProceedingJoinPoint point) throws Throwable{
  17. String methodname = point.getSignature().getName();
  18. System.out.println("环绕通知,执行"+methodname+"方法前");
  19. //选择执行
  20. point.proceed();
  21. System.out.println("环绕通知,执行"+methodname+"方法后");
  22. }
  23. }

(2)在applicationContext.xml文件做相关bean配置(部分代码)

  1. <bean id="userDao" class="com.dao.UserDao"/>
  2. <bean id="userService" class="com.service.UserService">
  3. <property name="userDao" ref="service"></property>
  4. </bean>
  5. <bean id="logAdvice" class="com.advice.LogAdvice"/>
  6. <aop:config>
  7. <!-- 配置一个切面 -->
  8. <aop:aspect id="logaop" ref="logAdvice" order="1">
  9. <!-- 定义切入点,表示对service的所有方法都进行拦截 -->
  10. <!--
  11. expression:用来匹配执行方法的连接点
  12. 第一个*表示匹配任意的方法的返回值
  13. 第一个..表示service包及其子包
  14. 第二个*表示所有类
  15. 第三个*表示所有方法
  16. 第二个..表示方法的任意参数个数
  17. -->
  18. <aop:pointcut expression="execution(* com.service.*.*(..))" id="testpointcut"/>
  19. <!-- 定义前置通知 -->
  20. <aop:before method="myBeforeAdvice" pointcut-ref="testpointcut"/>
  21. <!-- 定义后置通知 -->
  22. <aop:after method="myAfterAdvice" pointcut-ref="testpointcut"/>
  23. <!-- 定义环绕通知 -->
  24. <aop:around method="myAroundAdvice" pointcut-ref="testpointcut"/>
  25. </aop:aspect>
  26. </aop:config>
  27. </beans>

再写个测试类跑起来就可以了。


②通过拦截器判断用户是否可以执行目标代码的方法

(1)AuthorityInterceptor.java(用户权限拦截器)
功能:
admin用户可以执行add()和update()方法
register用户可以执行add()方法,但不可执行update()方法
other用户都不可以执行add()和update()方法

  1. package com.interceptor;
  2. import org.aopalliance.intercept.MethodInterceptor;
  3. import org.aopalliance.intercept.MethodInvocation;
  4. import com.bean.User;
  5. public class AuthorityInterceptor implements MethodInterceptor {
  6. private User user;
  7. public User getUser() {
  8. return user;
  9. }
  10. public void setUser(User user) {
  11. this.user = user;
  12. }
  13. public Object invoke(MethodInvocation arg0) throws Throwable {
  14. // TODO Auto-generated method stub
  15. System.out.println("拦截器==权限验证开始");
  16. String username=this.user.getUsername();
  17. String methodName = arg0.getMethod().getName();
  18. if(!username.equals("admin")&&!username.equals("register")) {
  19. System.out.println("没有任何执行权限");
  20. return null;
  21. }
  22. else if(username.equals("register")&&methodName.equals("update")) {
  23. System.out.println("register用户没有修改权限");
  24. return null;
  25. }
  26. else {
  27. Object object = arg0.proceed();
  28. System.out.println("拦截器==权限验证结束");
  29. return object;
  30. }
  31. }
  32. }

(2)LogInterceptor.java(用户操作日志拦截器)

  1. package com.interceptor;
  2. import org.aopalliance.intercept.MethodInterceptor;
  3. import org.aopalliance.intercept.MethodInvocation;
  4. public class LogInterceptor implements MethodInterceptor {
  5. public Object invoke(MethodInvocation arg0) throws Throwable {
  6. // TODO Auto-generated method stub
  7. String methodName = arg0.getMethod().getName();
  8. Object object = arg0.proceed();
  9. System.out.println("拦截器==日志记录:尝试执行"+methodName+"方法");
  10. return object;
  11. }
  12. }

(3)在applicationContext.xml文件做相关bean配置(部分代码)

  1. <bean id="admin" class="com.bean.User">
  2. <property name="username" value="admin"></property>
  3. <property name="password" value="123456"></property>
  4. </bean>
  5. <bean id="register" class="com.bean.User">
  6. <property name="username" value="register"></property>
  7. <property name="password" value="654321"></property>
  8. </bean>
  9. <bean id="other" class="com.bean.User">
  10. <property name="username" value="other"></property>
  11. <property name="password" value="666666"></property>
  12. </bean>
  13. <!-- -->
  14. <bean id="logInterceptor" class="com.interceptor.LogInterceptor"/>
  15. <bean id="authorityInterceptor" class="com.interceptor.AuthorityInterceptor">
  16. <!-- admin/register/other -->
  17. <property name="user" ref="admin"></property>
  18. </bean>
  19. <bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean">
  20. <property name="target" ref="userDao"></property>
  21. <property name="interceptorNames">
  22. <list>
  23. <value>authorityInterceptor</value>
  24. <value>logInterceptor</value>
  25. </list>
  26. </property>
  27. </bean>

激动人心的时刻到了,我们把成品跑起来!

测试类:

  1. package com.test;
  2. import org.springframework.context.support.ClassPathXmlApplicationContext;
  3. import com.service.UserService;
  4. public class Test {
  5. public static void main(String[] args) {
  6. // TODO Auto-generated method stub
  7. ClassPathXmlApplicationContext l = new ClassPathXmlApplicationContext("applicationContext.xml");
  8. UserService service = l.getBean("userService",UserService.class);
  9. service.add();
  10. l.close();//关闭流
  11. service.update();
  12. l.close();
  13. }
  14. }

applicationContext.xml(完整代码)

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:tx="http://www.springframework.org/schema/tx"
  6. xmlns:aop="http://www.springframework.org/schema/aop"
  7. xsi:schemaLocation="
  8. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  9. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
  10. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
  11. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
  12. <bean id="admin" class="com.bean.User">
  13. <property name="username" value="admin"></property>
  14. <property name="password" value="123"></property>
  15. </bean>
  16. <bean id="register" class="com.bean.User">
  17. <property name="username" value="register"></property>
  18. <property name="password" value="123"></property>
  19. </bean>
  20. <bean id="other" class="com.bean.User">
  21. <property name="username" value="other"></property>
  22. <property name="password" value="123"></property>
  23. </bean>
  24. <!-- -->
  25. <bean id="logInterceptor" class="com.interceptor.LogInterceptor"/>
  26. <bean id="authorityInterceptor" class="com.interceptor.AuthorityInterceptor">
  27. <!-- admin/register/other -->
  28. <property name="user" ref="admin"></property>
  29. </bean>
  30. <bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean">
  31. <property name="target" ref="userDao"></property>
  32. <property name="interceptorNames">
  33. <list>
  34. <value>authorityInterceptor</value>
  35. <value>logInterceptor</value>
  36. </list>
  37. </property>
  38. </bean>
  39. <bean id="userDao" class="com.dao.UserDao"/>
  40. <bean id="userService" class="com.service.UserService">
  41. <property name="userDao" ref="service"></property>
  42. </bean>
  43. <bean id="logAdvice" class="com.advice.LogAdvice"/>
  44. <aop:config>
  45. <!-- 配置一个切面 -->
  46. <aop:aspect id="logaop" ref="logAdvice" order="1">
  47. <!-- 定义切入点,表示对service的所有方法都进行拦截 -->
  48. <!--
  49. expression:用来匹配执行方法的连接点
  50. 第一个*表示匹配任意的方法的返回值
  51. 第一个..表示service包及其子包
  52. 第二个*表示所有类
  53. 第三个*表示所有方法
  54. 第二个..表示方法的任意参数个数
  55. -->
  56. <aop:pointcut expression="execution(* com.service.*.*(..))" id="testpointcut"/>
  57. <!-- 定义前置通知 -->
  58. <aop:before method="myBeforeAdvice" pointcut-ref="testpointcut"/>
  59. <!-- 定义后置通知 -->
  60. <aop:after method="myAfterAdvice" pointcut-ref="testpointcut"/>
  61. <!-- 定义环绕通知 -->
  62. <aop:around method="myAroundAdvice" pointcut-ref="testpointcut"/>
  63. </aop:aspect>
  64. </aop:config>
  65. </beans>

修改xml文件的联系用户id来显示不同用户下的打印结果。

  1. <bean id="authorityInterceptor" class="com.interceptor.AuthorityInterceptor">
  2. <!-- admin/register/other -->
  3. <property name="user" ref="admin"></property>
  4. </bean>

(1)admin
在这里插入图片描述
(2)register
在这里插入图片描述
(3)other
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,843人围观)

还没有评论,来说两句吧...

相关阅读