Spring AOP编程,即面向切面编程,那么什么是切面?先看下面的例子:
一个简单的加减乘除
public interface Calculate {
int add(int x,int y);
int sub(int x,int y);
int mul(int x,int y);
int div(int x,int y);
}
public class CalculateImpl implements Calculate {
public int add(int x, int y) {
return x+y;
}
public int sub(int x, int y) {
return x-y;
}
public int mul(int x, int y) {
return x*y;
}
public int div(int x, int y) {
return x/y;
}
}
如果在每次返回值之前,都要验证输入值的合法性,那么简单的实现就是在各个方法里加上相应的验证代码,这样整个方法就会显得很臃肿。并且一旦方法多了,其维护的难度也就很大了。如果还有其他业务方法,那么就更加不利于代码的维护了。
如上图,对于在很多方法都要执行的操作,我们把他们给抽离出来,如下:
Spring AOP之通知的类型:
AOP的基础是动态代理,其通知类型分为:前置通知,后置通知,返回通知,异常通知以及环绕通知。在进行aop编程的时候,需要引入相应的jar包,其对应maven的依赖为:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
配置文件中除开启扫描外,还需加入:
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
如果是使用的注解的方式,则需要添加如下的注解:
@EnableAspectJAutoProxy
切面类的实现如下:
//切面类:
@Aspect
@Component
public class LoggingAspect {
@Pointcut("execution(public * com.sg.aop.Calculate.*(..))")
public void declarePointCut(){}
/**
* 前置通知
* @param joinpoint
*/
@Before("declarePointCut()")
public void beforeMethod(JoinPoint joinpoint){
String shortString = joinpoint.getSignature().toShortString();
Object[] args = joinpoint.getArgs(); //获取传递的参数列表
Object target = joinPoint.getTarget().getClass().getName(); //目标对象
Object th= joinPoint.getThis().getClass().getName(); //被代理的对象
String modifiers = Modifier.toString(joinPoint.getSignature().getModifiers()); //获取修饰符的类型
List<Object> asList = Arrays.asList(args);
System.out.println("开始调用方法"+shortString+asList);
}
/**
* 无论是否发生异常,后置通知一定会执行
* 后置通知无法获取方法的执行结果
* @param joinpoint
*/
@After("declarePointCut()")
public void AfterMethod(JoinPoint joinpoint){
System.out.println("调用方法之后");
}
/**
* 返回通知,可以获取方法的返回值
* 只有在方法没有异常的时候,才会调用
* @param joinpoint
* @param result
*/
@AfterReturning(value="declarePointCut()",returning="result")
public void AfterReturning(JoinPoint joinpoint,Object result){
System.out.println("方法的返回值为:"+result);
}
/**
* 异常通知
* 其中Exception为异常的类型,意味发生此类异常的时候,才会进行捕捉
* @param joint
* @param e
* @return
*/
@AfterThrowing(value="declarePointCut()",throwing="e")
public Object AfterThrowing(JoinPoint joint,Exception e){
System.out.println("发生了异常");
return e;
}
@Around(value = "declarePointCut()")
public Object AroundAOP(ProceedingJoinPoint proceding){
Object proceed=null;
try {
System.out.println("before");
proceed= proceding.proceed();
System.out.println("after");
} catch (Throwable e) {
e.printStackTrace();
System.out.println("exception");
}
System.out.println("returing");
return proceed;
}
}
对于不同的切面的优先级,需要在相应的类上加上order注解,数字越小,优先级越高。