一、什么是SpringAOP
AOP就是在某一个类或方法执行前后打个标记,声明在执行到这里之前要先执行什么,执行完这里之后要接着执行什么。
二、AOP术语
1)连接点(Joinpoint)
通知分为
前置通知:before 在方法执行之前执行
后置通知:after 在方法执行之后执行(不管方法执行成功还是失败)
返回通知:afterReturning 在方法执行成功后执行
异常通知:afterThrowing 在方法发生异常后执行
环绕通知:around 在方法执行前后执行
三、Spring对AOP的支持
1.使用ProxyFactoryBean和对应的接口实现AOP
2.使用XML配置AOP
3.使用@AspectJ注解驱动切面
4.使用AspectJ注入切面
四、使用@AspectJ注解开发AOP(优先)
0.Spring实现的是一个方法级别的AOP框架,动态代理的方式拦截指定方法的通知
1.创建切面
在Spring中使用@Aspect注解一个类,SpringIOC容器就会将其当作一个切面。
切面类中的方法可以通过加上以下注解作为通知
@Before 前置通知
@After 后置通知
@Around 环绕通知
@AfterReturning 正常返回通知
package club.llf.aspect;
import org.aspectj.lang.annotation.*;
@Aspect
public class XXXAspect {
@Before("execution(* club.llf.service.impl.UserServiceImpl.printUser(..))")
public void before(){
System.out.println("前置通知");
}
@After("execution(* club.llf.service.impl.UserServiceImpl.printUser(..))")
public void after(){
System.out.println("后置通知");
}
@AfterReturning("execution(* club.llf.service.impl.UserServiceImpl.printUser(..))")
public void afterReturning(){
System.out.println("返回通知");
}
@AfterThrowing("execution(* club.llf.service.impl.UserServiceImpl.printUser(..))")
public void afterThrowing(){
System.out.println("异常通知");
}
@Around("execution(* club.llf.service.impl.UserServiceImpl.printUser(..))")
public void around(ProccedingJoinPoint jp){
System.out.println("环绕通知前");
jp.proceed();
System.out.println("环绕通知后")
}
}
execution : 执行方法时触发
* : 任意返回值的方法
club.llf.service.impl.UserServiceImpl.printUser : 拦截指定方法名
(..) : 方法的参数任意
3.为了少写重复的正则表达式,可以使用@Pointcut注解来避免,修改如下
package club.llf.aspect;
import org.aspectj.lang.annotation.*;
@Aspect
public class XXXAspect {
@Pointcut("execution(* club.llf.service.impl.UserServiceImpl.printUser(..))")
public void print(){
}
@Before("print()")
public void before(){
System.out.println("前置通知");
}
@After("print()")
public void after(){
System.out.println("后置通知");
}
@AfterReturning("print()")
public void afterReturning(){
System.out.println("返回通知");
}
@AfterThrowing("print()")
public void afterThrowing(){
System.out.println("异常通知");
}
@Around("print()")
public void around(ProccedingJoinPoint jp){
System.out.println("环绕通知前");
jp.proceed();
System.out.println("环绕通知后")
}
}
五、开启AOP自动代理
1.注解方式
注解配置类如下(也可以给切面类加上@Component,并且扫描其所在包,那么就可以不配置下面的@Bean了)
@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages={"club.llf.pojo"})
public class AOPConfig{
@Bean
public RoleAspect getRoleAspect(){
return new XXXAspect();
}
}
2.XML方式
<aop:aspectj-autoproxy/>
<bean id="xxxAspect" class="club.llf.aspect.XXXAspect"/>
....
六、参数传递和引入
1.参数传递
在正则表达式中书写 execution(* club.llf.service.impl.UserServiceImpl.printUser(..) && args(参数名1,参数名2))
注解方法中加入和正则中相同的参数名即可完成传递。(参数名 一般是方法的真实参数名)
@AfterReturning("execution(* club.llf.service.impl.UserServiceImpl.printUser(..) && args(role,sort))")
public void afterReturning(Role role,int sort){
System.out.println("返回通知");
}
2.引入
引入一般是对原有类没有的功能进行拓展
实现步骤