AOP:全称是Aspect Oriented Programming,面向切面编程
Spring AOP的作用和优势:
- 作用:在程序运行期间,不修改源码对已有方法进行增强
- 优势:减少重复代码;提高开发效率;维护方便
Spring AOP的实现方式:
- 使用Java的动态代理技术
- 通过配置的方式
Spring AOP相关术语:
- JoinPoint(连接点):指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点。
- Pointcut(切入点):指我们要对哪些JoinPoint进行拦截的定义。
- Advice(通知/增强):指拦截到oinpoint之后要做的事情就是通知。通知的类型:前置通知、后置通知、异常通知、最终通知、环绕通知。
使用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: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/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="accountService" class="com.lin.service.impl.AccountServiceImpl"/>
<!--spring中基于XML的AOP配置步骤
1、把通知Bean也交给spring来管理
2、使用aop:config标签表明开始AOP的配置:
3、使用aop:aspect标签表明配置切面
id属性:是给切面提供一个唯一表示
ref属性:是指定通知类bean的Id
4、在aop:aspect标签的内部使用对应标签来配置通知的类型
这里示例是让printLog方法在切入点方法执行之前:所以是前置通知
aop:before:表示配置前置通知
method属性:用于指定Logger类中哪个方法是前置通知
pointcut属性:用于指定切入点表达式,指对业务层中哪些方法增强
切入点表达式的写法:
关键字:execution(表达式)
表达式:
访问修饰符 返回值 包名.包名...类名.方法名(参数列表)
标准表达式写法:
public void com.lin.service.impl.AccountServiceImpl.saveAccount()
-->
<bean id="logger" class="com.lin.util.Logger"/>
<aop:config>
<aop:aspect id="logAdvice" ref="logger">
<aop:pointcut id="pt1" expression="execution(public void com.lin.service.impl.AccountServiceImpl.saveAccount())"/>
<aop:before method="printLog"
pointcut-ref="pt1"/>
</aop:aspect>
</aop:config>
</beans>
使用注解配置的时候,配置如下:
-
xml文件中开启AOP注解:
<!--开启spring注解AOP支持--> <aop:aspectj-autoproxy/>
-
类中注解如下:
/** * 用于记录日志的工具,提供公共代码 * Create by ljc on 2019/11/2 */ @Component("logger") @Aspect //表示当前类是一个切面类 public class Logger { @Pointcut("execution(* com.lin.service.impl.*.*(..))") private void pt1() { } @Before("pt1()") public void beforePrintLog() { System.out.println("前置通知Logger类中的printLog方法开始记录日志...."); } @After("pt1()") public void afterPrintLog() { System.out.println("后置通知Logger类中的printLog方法开始记录日志...."); } }