AOP的前世今生之后续
1. 概述
上篇文章【Spring 深入学习】AOP的前世今生之代理模式我们讲述了代理模式。而我们今天的主人公
AOP
就是基于代理模式实现的,所以我们今天会简单学习下AOP
2. 什么是AOP
是面向切面编程,一般可以帮助我们在不修改现有代码的情况下,对程序的功能进行拓展,往往用于实现 日志处理,权限控制,性能检测,事务控制等
3. 核心概念
- 连接点
- 类里面那些可以被增强的方法,这些方法称之为连接点
- 表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point
上述的方法都可以称之为连接点。
- 切入点
- 实际被增强的方法,称之为切入点
- 表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方
虽然上述的截图中存在两个方法,但是实际只会增强一个方法,就是addUser
. 这个方法就是切入点
- 目标对象
- 实际增强的逻辑部分称为通知 (增加的功能)
- Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
通知类型: 1 前置通知 2 后置通知 3 环绕通知 4 异常通知 5 最终通知
这种实际被作用的方法就是目标对象
- 切面
表现为功能相关的一些advice方法放在一起声明成的一个Java类
整个类文件DaoAspect
其实就是切面
- 织入
创建代理对象并实现功能增强的声明并运行过程
4. 多种AOP方式
@Component
@Aspect
public class DaoAspect {
@Pointcut(value = "execution(* plus.chendd.dao.UserDao.addUser(..))")
public void addPointCut() {}
/**
* 前置通知
* @param joinPoint
*/
@Before("addPointCut()")
public void beforeMethod(JoinPoint joinPoint) {
System.out.println("beforeMethod ... 前置通知");
Object[] args = joinPoint.getArgs();
System.out.println(args);
}
/**
* 后置通知 无论结果是否异常 都会执行
*/
@After("addPointCut()")
public void afterMethod() {
System.out.println("afterMethod ... 后置通知");
}
/**
* 返回通知 被代理方法执行后 执行此方法,如果发生了异常 不执行此方法
* @param joinPoint
* @param res
*/
@AfterReturning(value = "addPointCut()", returning = "res")
public void afterMethodReturning(JoinPoint joinPoint, Object res) {
System.out.println(res);
System.out.println("afterMethodReturning ... 返回通知");
}
/**
* 异常通知 如果方法一旦发生了异常 执行此方法
* @param ex
*/
@AfterThrowing(value = "execution(* plus.chendd.dao.UserDao.updateUser(..))", throwing = "ex")
public void methodAfterThrowing(Exception ex) {
System.out.println("methodAfterThrowing ... 异常通知");
}
/**
* 环绕通知:被代理的方法执行前后 都会执行此方法
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around(value = "addPointCut()")
public Object methodAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("methodAround ... 环绕通知 前");
Object o = proceedingJoinPoint.proceed();
System.out.println("methodAround ... 环绕通知 后");
return o;
}
}
运行结果
结论
环绕通知(前) > 前置通知 > 返回通知 > 后置通知 > 环绕通知(后)
5. 开启AOP多种方式
通过配置文件
@Configuration
@ComponentScan(basePackages = "plus.chendd")
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class SpringConfig {
}
代码@EnableAspectJAutoProxy(proxyTargetClass = true)
用来开启AOP的
通过xml文件
<!--创建对象-->
<bean id="userDao" class="com.com.msb.UserDaoImpl"></bean>
<bean id="daoAspect" class="com.com.aspect.DaoAspect"></bean>
<!--配置aop增强-->
<aop:config>
<!--切入点-->
<aop:pointcut id="pointCutAdd" expression="execution(* com.msb.dao.UserDao.add*(..))"/>
<!--配置切面-->
<aop:aspect ref="daoAspect">
<!--增强作用在具体的方法上-->
<aop:before method="methodBefore" pointcut-ref="pointCutAdd"/>
<aop:after method="methodAfter" pointcut-ref="pointCutAdd"/>
<aop:around method="methodAround" pointcut-ref="pointCutAdd"/>
<aop:after-returning method="methodAfterReturning" pointcut-ref="pointCutAdd" returning="res"/>
<aop:after-throwing method="methodAfterThrowing" pointcut-ref="pointCutAdd" throwing="ex"/>
</aop:aspect>
</aop:config>
6. 结论
Spring 两大核心思想就是IOC, AOP.
AOP
的重要性可想而知啊。所以上述的知识掌握是非常有必须要的。具体的实例参照 demo 源码