AOP
面向切面编程:面向对象编程中,重复性代码问题单独解决,是对oop(面向对象的补充)
-
切面:aspct 切入点:如:事物、权限、日志打印等
-
将横切关注点的代码查找到后,单独形成的类称为切面类(都是非业务代码)。将扩展代码程序组
-
件化
-
(具有复用性和可维护性)。
-
横切关注点:
就是要查找到解决问题代码都在什么地方。指的是那些非业务代码。 -
通知(Advice):将非业务代码从目标类中独立出来,放置到切面类的方法中进行编写。
-
切面类中的方法,称为通知方法。
前置通知:在执行目标方法前执行的功能扩展。
方法返回通知:在执行目标方法返回结果时执行的功能扩展。
异常通知:在执行目标方法有异常时执行的功能扩展。
后置(最终)通知:在执行目标方法后,不管是否存在异常,都将执行的功能扩展。
环绕通知:相当于以上四种通知的组合。 -
连接点
-
目标对象中需要执行功能扩展的点,称为连接点。 在Spring的AOP中,连接点就是目标对象的方法
-
切入点
-
需要将执行扩展的目标类中的方法(连接点)查找出来,可采用切入点表达式来查找。 查找到的连接点统一称为切入点。(切入点是一些连接点的集合)
-
目标: 需要进行功能扩展的对象称为目标对象。连接点方法所在的类
-
代理
@Aspect
@Component
public class LogAspect {
}
//@Before 表示声明一个方法为前置通知方法。前置通知方法应该在目标方法调用前执行。
@Before(value=“execution(public int com.xxxx.spring.bean.EazyImpl.*(int, int))”)
public void startLog(){
System.out.println(“方法开始了”);//横切关注点
}
AspectJ支持5种类型的通知注解:
[1]@Before:前置通知,在方法执行之前执行
[2]@After:后置通知,在方法执行之后执行
[3]@AfterRunning:返回通知,在方法返回结果之后执行
[4]@AfterThrowing:异常通知,在方法抛出异常之后执行
[5]@Around:环绕通知,围绕着方法执行
execution([权限修饰符] [返回值类型] [简单类名/全类名] 方法名)
获取连接点信息★
框架将连接点方法的进行封装为org.aspectj.lang.JoinPoint对象,可以通过这个JoinPoint对象获取方法的参数和名称等信息
Object[] args = joinPoint.getArgs();
Signature signature = joinPoint.getSignature();
String name = signature.getName();
方法返回通知中获取连接点方法的返回结果
如果客户端希望获取目标对象方法的返回结果,那么,可以在方法返回通知中获取目标方法返回结果,然后通过return返回给客户端
//方法返回通知:在目标方法执行结果返回时执行。
@AfterReturning(value=“execution(public int com.xxxxx.spring.bean.EazyImpl.*(int, int))”,returning=“result”)
public Object retuningLog(JoinPoint joinPoint,**Object result){
Object[] args = joinPoint.getArgs();
Signature signature = joinPoint.getSignature();
String name = signature.getName();
System.out.println(name+"方法返回了,结果是="+result);//横切关注点
**return result;**
}
//异常通知:在目标方法执行过程中抛出异常时执行
@AfterThrowing(value=“execution(public int com.xxxx.spring.bean.EazyImpl.*(int, int))”,throwing=“e”)
public void throwingLog(JoinPoint joinPoint,Throwable e) throws Throwable{
Object[] args = joinPoint.getArgs();
Signature signature = joinPoint.getSignature();
String name = signature.getName();
System.out.println(name+"方法出现异常了-异常是="+e.getMessage());//横切关注点
throw e ;
}
@Around(value=“execution(public int com.xxxx.spring.bean.EazyImpl.*(int, int))”)
public Object aroundLog(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
Object result = null ;
Object[] args = proceedingJoinPoint.getArgs();
Signature signature = proceedingJoinPoint.getSignature();
String name = signature.getName();
try {
System.out.println(“aroundLog-”+name+“方法开始了,参数:”+Arrays.asList(args));//横切关注点
result = proceedingJoinPoint.proceed(); //调用目标方法——执行连接点
System.out.println("aroundLog-"+name+"方法返回了,结果是="+result);//横切关注点
} catch (Throwable e) {
e.printStackTrace();
System.out.println("aroundLog-"+name+"方法出现异常了-异常是="+e.getMessage());//横切关注点
throw e ; //捕获异常后,将异常一定抛出,否则外层方法无法获取异常对象
} finally{
System.out.println("aroundLog-"+name+"方法最终执行了");//横切关注点
}
return result ; //环绕通知方法一定将目标方法的返回结果返回给外层方法;
}
定义公共切入点表达式
//定义公共的切入点表达式
@Pointcut(value=“execution(public int com.xxxxx.spring.bean.EazyImpl.*(int, int))”)
public void pointcut(){}
使用通知注解引用公共的切入点表达式
@Before(value=“pointcut()”)
@AfterReturning(pointcut=“pointcut()”,returning=“result”)
@AfterThrowing(pointcut=“pointcut()”,throwing=“e”)
@After(value=“pointcut()”)
@Around(value=“pointcut()”)