AOP(面向切面编程)
在软件业,AOP为Aspect Oriented Programming的缩写,意为:
面向切面编程,通过
预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是
OOP的延续,是软件开发中的一个热点,也是
Spring框架中的一个重要内容,是
函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的
耦合度降低,提高程序的可重用性,同时提高了开发的效率。
aop面向切面编程,对于切面编程的学习,我理解的是在程序中有很多重复的字段,在切面中作为切点,我们为了方便以后的修改以及代码的优化,将这些切点抽取出来,作为切面来统一的管理。
aop中给了一些关键的几个注解让我们来操作aop,分别是@Before,@After,@AfterReturning,@AfterThrowing,@Around。等让我们来对我们的功能进行操作。
@Before:前置通知: 在方法执行之前执行,记录目标方法的执行开始位置
@After:后置通知: 在方法执行之后执行,记录目标方法的执行结束位置
注:1.后置通知得不到方法返回值 2.不管方法是否发生异常度执行
@AfterReturning:在目标方法执行之后执行,可以访问目标方法的执行结果
注:(异常之后不执行)
@AfterThrowing,异常通知:在目标方法发生异常时候执行,可以访问到异常对象
@Around。环绕通知:需要携带ProceedingJoinPoint类型的参数,可以决定是否执行目标方法
注: 1.环绕通知类似动态代理全过程
2.环绕通知必须有返回值,返回值即为目标方法的返回值
@Before:前置通知: 在方法执行之前执行,记录目标方法的执行开始位置
@After:后置通知: 在方法执行之后执行,记录目标方法的执行结束位置
注:1.后置通知得不到方法返回值 2.不管方法是否发生异常度执行
@AfterReturning:在目标方法执行之后执行,可以访问目标方法的执行结果
注:(异常之后不执行)
@AfterThrowing,异常通知:在目标方法发生异常时候执行,可以访问到异常对象
@Around。环绕通知:需要携带ProceedingJoinPoint类型的参数,可以决定是否执行目标方法
注: 1.环绕通知类似动态代理全过程
2.环绕通知必须有返回值,返回值即为目标方法的返回值
对于aop的运用:
方法有两种,一种在代码中注入:
@Before("execution(* *.*.*.add(..))")
@After("execution(* *.*.*.add(..))")
@AfterReturning(value = "execution(* *.*.*.add(..))",returning = "result")
@AfterThrowing(value = "execution(* *.*.*.add(..))",throwing = "e")
@Around(value = "execution(* *.*.*.add(..))")
方法有两种,一种在代码中注入:
@Before("execution(* *.*.*.add(..))")
@After("execution(* *.*.*.add(..))")
@AfterReturning(value = "execution(* *.*.*.add(..))",returning = "result")
@AfterThrowing(value = "execution(* *.*.*.add(..))",throwing = "e")
@Around(value = "execution(* *.*.*.add(..))")
这种形式。但是需要注意的是要在sping中声明;<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
另外一种:在xml中直接声明配置:
<aop:config>
<aop:pointcut expression="execution(* *.*.*.add(..))" id="logMathPointcut"/>
<aop:aspect ref="logAsMath" order="1">
<aop:before method="beforeMethod" pointcut-ref="logMathPointcut"/>
<aop:after method="afterMethod" pointcut-ref="logMathPointcut"/>
<aop:after-returning method="afterReturnMethod" pointcut-ref="logMathPointcut" returning="result"/>
<aop:after-throwing method="afterThrowingMethod" pointcut-ref="logMathPointcut" throwing="e"/>
</aop:aspect>
</aop:config>
首先MathTest.java:
package com.bean;
import java.util.Arrays;
import org.springframework.stereotype.Component;
@Component
public class MathTest {
public int add(int a,int b){
System.out.println("this is run ");
int z = a+b;
System.out.println("this is run result"+z);
return a+b;
}
public int sub(int a,int b){
System.out.println("this is run ");
int z = a-b;
System.out.println("this is run result"+z);
return a-b;
}
public int mul(int a,int b){
System.out.println("this is run ");
int z = a*b;
System.out.println("this is run result"+z);
return a*b;
}
public int div(int a,int b){
System.out.println("this is run ");
int z = a/b;
System.out.println("this is run result"+z);
return a/b;
}
}
对于这个文件来说,我们要运行出结果,并打印出日志输出,但是每一个运行都要写出重复的句子,这对于我们的程序来说是有很多的剩余,对程序的管理来说也不好,比如以后要需改的时候,更是麻烦,所以aop就给我们带来了方面,将需要重复的句子抽离出来,作为切点,组成切面来统一管理.以下是运用aop来管理:
MathTest.java
package com.bean;
import java.util.Arrays;
import org.springframework.stereotype.Component;
@Component
public class MathTest {
public int add(int a,int b){
return a+b;
}
public int sub(int a,int b){
return a-b;
}
public int mul(int a,int b){
return a*b;
}
public int div(int a,int b){
return a/b;
}
}
建立aop的管理代码:
LogAs.java:
package com.bean;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
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.springframework.stereotype.Component;
@Aspect
@Component
public class LogAs {
@Before("execution(* *.*.*.add(..))")
public void beforeMethod(JoinPoint joinpoint){
Object[] args = joinpoint.getArgs();
String name = joinpoint.getSignature().getName();
System.out.println("this is run "+name+" before "+Arrays.asList(args));
}
@After("execution(* *.*.*.add(..))")
public void afterMethod(JoinPoint joinpoint){
Object[] args = joinpoint.getArgs();
String name = joinpoint.getSignature().getName();
System.out.println("this is run "+name+" after "+Arrays.asList(args));
}
@AfterReturning(value = "execution(* *.*.*.add(..))",returning = "result")
public void afterReturnMethod(JoinPoint joinpoint,Object result){
Object[] args = joinpoint.getArgs();
String name = joinpoint.getSignature().getName();
System.out.println("this is run "+name+" after "+"return result "+result);
}
@AfterThrowing(value = "execution(* *.*.*.add(..))",throwing = "e")
public void afterThrowingMethod(JoinPoint joinpoint,Throwable e){
Object[] args = joinpoint.getArgs();
String name = joinpoint.getSignature().getName();
System.out.println("this is run "+name+" after "+"thowable :异常 "+e);
}
@Around(value = "execution(* *.*.*.add(..))")
public void Around(ProceedingJoinPoint joinPoint){
Object proceed = null;
String name = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
try {
System.out.println("this is run "+name+" before "+Arrays.asList(args));
proceed = joinPoint.proceed();
System.out.println("this is run "+name+" after "+Arrays.asList(args));
} catch (Throwable e) {
System.out.println("this is run "+name+" after "+"thowable :异常 "+e);
e.printStackTrace();
}
System.out.println("this is run "+name+" after "+"return result "+proceed);
}
}
这就将我们的复杂代码能统一的管理,对于以后的修改也方便了很多,但是要注意要在配置文件中添加一句话
applicationContext.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<context:component-scan base-package="com,test"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!--
<aop:config>
<aop:pointcut expression="execution(* *.*.*.add(..))" id="logMathPointcut"/>
<aop:aspect ref="logAsMath" order="1">
<aop:before method="beforeMethod" pointcut-ref="logMathPointcut"/>
<aop:after method="afterMethod" pointcut-ref="logMathPointcut"/>
<aop:after-returning method="afterReturnMethod" pointcut-ref="logMathPointcut" returning="result"/>
<aop:after-throwing method="afterThrowingMethod" pointcut-ref="logMathPointcut" throwing="e"/>
</aop:aspect>
</aop:config>
-->
</beans>
注释的是在xml中声明,不用在代码中注入,就不写代码了,aop中有很多奥妙的地方,需要大家细细领悟,当然,有什么好的意见,可以写出,多多交流!