一.AOP是什么?
面向切面编程,就是将交叉业务逻辑封装成切面,利用AOP功能将切面织入到主业务逻辑中。交叉业务逻辑就是通用的,与主业务逻辑无关的代码。比如日志记录,事务管理,异常处理,安全控制。
二.AOP优点
1.降低了代码的耦合度
2.提高了代码的重用性,减轻了程序员的工作量
3.系统更加容易扩展
三.AOP关键字
1.切面:泛指交叉的业务逻辑。比如日志记录,事务管理就是一个切面。
2.切点:符合切点表达式的连接点,也就是被切入的位置
3.通知:切面类要完成工作,切面类的工作就是通知,通知定义了切面做什么以及何时使用。
四.AOP的实现
AOP的底层实现就是反射加上代理模式。
反射和代理模式可以参考我之前的博客。
反射:https://blog.csdn.net/x_christ1/article/details/104591277
代理模式:https://blog.csdn.net/x_christ1/article/details/104594560
五.AOP的使用方式
1.注解使用
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> 开启事物注解权限
@Aspect 指定一个类为切面类
@Pointcut("execution(* com.xhz.service.UserService.add(..))") 指定切入点表达式
@Before("pointCut_()") 前置通知: 目标方法之前执行
@After("pointCut_()") 后置通知:目标方法之后执行(始终执行)
@AfterReturning("pointCut_()") 返回后通知: 执行方法结束前执行(异常不执行)
@AfterThrowing("pointCut_()") 异常通知: 出现异常时候执行
@Around("pointCut_()") 环绕通知: 环绕目标方法执行
@Component
@Aspect
public class AopLog {
// 前置通知
@Before("execution(* com.cxy.service.UserService.add(..))")
public void begin() {
System.out.println("前置通知");
}
//
// 后置通知
@After("execution(* com.cxy.service.UserService.add(..))")
public void commit() {
System.out.println("后置通知");
}
// 运行通知
@AfterReturning("execution(* com.cxy.service.UserService.add(..))")
public void returning() {
System.out.println("运行通知");
}
// 异常通知
@AfterThrowing("execution(* com.cxy.service.UserService.add(..))")
public void afterThrowing() {
System.out.println("异常通知");
}
// 环绕通知
@Around("execution(* com.cxy.service.UserService.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕通知开始");
proceedingJoinPoint.proceed();
System.out.println("环绕通知结束");
}
}
2.通过xml方式
<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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- dao 实例 -->
<bean id="userService" class="com.cxy.service.UserService"></bean>
<!-- 切面类 -->
<bean id="aop" class="com.cxy.aop2.AopLog2"></bean>
<!-- Aop配置 -->
<aop:config>
<!-- 定义一个切入点表达式: 拦截哪些方法 -->
<aop:pointcut expression="execution(* com.cxy.service.UserService.*(..))"
id="pt" />
<!-- 切面 -->
<aop:aspect ref="aop">
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pt" />
<!-- 前置通知: 在目标方法调用前执行 -->
<aop:before method="begin" pointcut-ref="pt" />
<!-- 后置通知: -->
<aop:after method="after" pointcut-ref="pt" />
<!-- 返回后通知 -->
<aop:after-returning method="afterReturning"
pointcut-ref="pt" />
<!-- 异常通知 -->
<aop:after-throwing method="afterThrowing"
pointcut-ref="pt" />
</aop:aspect>
</aop:config>
</beans>
public class AopLog2 {
// 前置通知
public void begin() {
System.out.println("前置通知");
}
//
// 后置通知
public void commit() {
System.out.println("后置通知");
}
// 运行通知
public void returning() {
System.out.println("运行通知");
}
// 异常通知
public void afterThrowing() {
System.out.println("异常通知");
}
// 环绕通知
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕通知开始");
proceedingJoinPoint.proceed();
System.out.println("环绕通知结束");
}
}