Spring全家桶(八)AOP核心思想与AspectJ 5种类型通知
来源:互联网 发布:flask sql session 编辑:程序博客网 时间:2024/06/02 16:20
一、AOP核心思想
AOP是Aspect-Oriented Programming的缩写,翻译为面向切面编程。我个人理解切面就是一个方面。
例子,一个接口里面有增删改查四个方法:
package com.stuspring.aop.impl;/** * Created by bee on 17/5/15. */public interface ArithmeticCalculator { int add(int i,int j); int sub(int i,int j); int mul(int i,int j); int div(int i,int j);}
实现类:
package com.stuspring.aop.impl;import org.springframework.stereotype.Component;/** * Created by bee on 17/5/15. */@Component("arithmeticCalculator")public class ArithmeticCalculatorImpl implements ArithmeticCalculator { @Override public int add(int i, int j) { int result=i+j; return result; } @Override public int sub(int i, int j) { int result=i-j; return result; } @Override public int mul(int i, int j) { int result=i*j; return result; } @Override public int div(int i, int j) { int result=i/j; return result; }}
如果想给这四个方法分别加上前置日志功能,以其中一个为例,add方法变这样:
@Override public int add(int i, int j) { System.out.println("The method add begins with " +i+","+j); int result=i+j; return result; }
手动给每个方法都加上固然可行,但是维护起来过于麻烦,面向切面编程就是为了解决这一问题。AOP的好处就是每个逻辑位于一个位置,代码不分散便于维护和升级,业务模块更简洁。
加一个日志切面:
package com.stuspring.aop.impl;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.springframework.stereotype.Component;import java.util.Arrays;import java.util.List;/** * Created by bee on 17/5/15. */@Aspect@Componentpublic class LoggingAspect { /** * 前置通知 方法开始之前执行 * @param joinPoint */ @Before("execution(public int com.stuspring.aop.impl.ArithmeticCalculatorImpl.*(int,int))") public void beforeMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); List<Object> agrs = Arrays.asList(joinPoint.getArgs()); System.out.println("The method " + methodName + " begins with " + agrs); } /** * 后置通知,方法执行完之后执行,不论方法是否出现异常 * 后置通知中不能访问目标方法的执行结果 */ @After("execution(public int com.stuspring.aop.impl.ArithmeticCalculatorImpl.*(int,int))") public void afterMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); List<Object> args = Arrays.asList(joinPoint.getArgs()); System.out.println("The method " + methodName + " ends with " + args); }}
新建spring配置文件beans-aspect.xml:
<?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:content="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/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <content:component-scan base-package="com.stuspring.aop.impl"/> <aop:aspectj-autoproxy/></beans>
附maven依赖:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.8.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.8.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.3.8.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.3.8.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.10</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.10</version> </dependency>
二、五种类型通知
@Before前置通知:方法开始之前执行。
/** * 前置通知 方法开始之前执行 * @param joinPoint */ @Before("execution(public int com.stuspring.aop.impl.ArithmeticCalculatorImpl.*(int,int))") public void beforeMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); List<Object> agrs = Arrays.asList(joinPoint.getArgs()); System.out.println("The method " + methodName + " begins with " + agrs); }
@After后置通知:方法开始之后执行,不论方法是否出现异常。
/** * 后置通知,方法执行完之后执行,不论方法是否出现异常 * 后置通知中不能访问目标方法的执行结果 */ @After("execution(public int com.stuspring.aop.impl.ArithmeticCalculatorImpl.*(int,int))") public void afterMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); List<Object> args = Arrays.asList(joinPoint.getArgs()); System.out.println("The method " + methodName + " ends with " + args); }
@AfterRunning:返回通知,在方法返回结果之后执行。
/** * 返回通知,在方法正常结束之后执行的代码 * 返回通知可以访问方法的返回值 */ @AfterReturning(value="execution(public int com.stuspring.aop.impl.ArithmeticCalculatorImpl.*(int,int))",returning = "result") public void afterReturning(JoinPoint joinPoint,Object result){ String methodName=joinPoint.getSignature().getName(); System.out.println("The method "+methodName+" ends with "+result); }
@AfterThrowing:异常通知,在方法抛出异常之后。
/** * 异常通知:在方法抛出异常之后执行 * @param joinPoint * @param e */ @AfterThrowing(value="execution(public int com.stuspring.aop.impl.ArithmeticCalculatorImpl.*(int,int))",throwing = "e") public void afterThrowing(JoinPoint joinPoint,Exception e){ String methodName=joinPoint.getSignature().getName(); System.out.println("The method "+methodName+" occurs execution: "+e); }
@Around:环绕通知,围绕方法执行。
/** * 环绕通知需要携带ProceedingJoinPoint类型的参数 * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法 * 环绕通知必须有返回值,返回值即为目标方法的返回值 * * @param pjd */ @Around("execution(public int com.stuspring.aop.impl.ArithmeticCalculatorImpl.*(..))") public Object aroundMethod(ProceedingJoinPoint pjd) { Object result = null; String methodName = pjd.getSignature().getName(); try { //前置通知 System.out.println("--->The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs())); //执行目标方法 result = pjd.proceed(); //后置通知 System.out.println("--->The method " + methodName + " ends with " + result); } catch (Throwable e) { //异常通知 System.out.println("The method "+methodName+" occurs exception : "+e); } //后置通知 System.out.println("The Method "+methodName+" ends!"); return result; }
三、指定切面的优先级
切面的优先级可以用@Order注解指定,传入的整数值越小,优先级越高。
四、复用切点表达式
/** * 定义一个方法用于声明切入点表达式。一般地,该方法不需要再写其它代码。 */ @Pointcut("execution(public int com.stuspring.aop.impl.ArithmeticCalculatorImpl.*(int,int))") public void declareJoinPointExpression(){ } /** * 前置通知 方法开始之前执行 * @param joinPoint */ @Before("declareJoinPointExpression()") public void beforeMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); List<Object> agrs = Arrays.asList(joinPoint.getArgs()); System.out.println("The method " + methodName + " begins with " + agrs); }
外部类引用可以使用报名加方法名的方法。
五、配置文件方式配置AOP
接口:
package com.stuspring.aop.fileimpl;/** * Created by bee on 17/5/16. */public interface ArithmeticCalculator { int add(int i,int j); int sub(int i,int j); int mul(int i,int j); int div(int i,int j);}
实现类:
package com.stuspring.aop.fileimpl;/** * Created by bee on 17/5/16. */public class ArithmeticCalculatorImpl implements ArithmeticCalculator { @Override public int add(int i, int j) { int result=i+j; return result; } @Override public int sub(int i, int j) { int result=i-j; return result; } @Override public int mul(int i, int j) { int result=i*j; return result; } @Override public int div(int i, int j) { int result=i/j; return result; }}
日志切面:
package com.stuspring.aop.fileimpl;import org.aspectj.lang.JoinPoint;/** * Created by bee on 17/5/16. */public class LoggingAspect { public void beforeMethod(JoinPoint joinPoint){ String methodName=joinPoint.getSignature().getName(); System.out.println("The method begins with "+methodName); }}
参数验证切面:
package com.stuspring.aop.fileimpl;import org.aspectj.lang.JoinPoint;/** * Created by bee on 17/5/16. */public class ValidationAspect { public void validateArgs(JoinPoint joinPoint){ System.out.println("validationMethod......"); }}
Spring配置文件:
<?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.3.xsd"> <!--配置bean--> <bean id="arithmeticCalculator" class="com.stuspring.aop.fileimpl.ArithmeticCalculatorImpl"/> <bean id="loggingAspect" class="com.stuspring.aop.fileimpl.LoggingAspect"/> <bean id="validationAspect" class="com.stuspring.aop.fileimpl.ValidationAspect"/> <aop:config> <!--配置切面表达式--> <aop:pointcut id="pointcut" expression="execution(public int com.stuspring.aop.fileimpl.ArithmeticCalculatorImpl.*(int,int))"/> <!--配置切面通知--> <aop:aspect ref="loggingAspect" order="2"> <aop:before method="beforeMethod" pointcut-ref="pointcut"/> </aop:aspect> <aop:aspect ref="validationAspect" order="1"> <aop:before method="validateArgs" pointcut-ref="pointcut"/> </aop:aspect> </aop:config></beans>
Main测试方法:
package com.stuspring.aop.fileimpl;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * Created by bee on 17/5/16. */public class Main { public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("beans-aspectfile.xml"); ArithmeticCalculator calculator= (ArithmeticCalculator) ctx.getBean("arithmeticCalculator"); System.out.println(calculator.add(2,4)); }}
阅读全文
2 0
- Spring全家桶(八)AOP核心思想与AspectJ 5种类型通知
- Spring IoC与AOP的核心思想
- Spring AOP与Aspectj
- spring aop 与 aspectj
- spring aop 环绕通知 基于@aspectJ
- aop,spring aop,aspectj区别与联系
- Spring IoC与AOP的核心思想(转载)
- Spring IoC与AOP的核心思想(转载)
- Spring——AOP核心思想与实现
- spring中的AOP与AspectJ的区别?
- Spring AOP 实现和一些核心思想
- Spring AOP学习11 - Spring AOP 与 AspectJ
- 我的Spring之旅——(三)AOP通知的几种类型
- Spring---AOP基本概念以及Advice5种类型的通知注解应用实例
- Spring AOP + AspectJ framework
- spring AspectJ aop学习
- spring aop AspectJ
- Spring AOP + AspectJ annotation
- 【蓝桥杯第六届javaB组国赛】表格计算
- Arcgis---the Vertical extent is too large for proper display
- 最全解析:大数据和机器学习有什么区别
- Linux中mysql无法启动 报错 the server quit without updating PID file的解决方法
- python实现支持向量机SVM算法
- Spring全家桶(八)AOP核心思想与AspectJ 5种类型通知
- Nexus 3和Nginx配置docker私有栈
- centos定时备份mysql数据库 用shell脚本实现
- React组件API
- 研发中心项目管理助理招聘需求
- DHTML技术---正则表达式和onblur方法学习
- web前端开发总结
- xhprof性能分析学习
- 使用BusyBox制作根文件系统的理论分析