一.Aop:【动态代理】
指在程序运行期间动态的将其某段代码切入到指定方法指定位置进行运行的编程方式
步骤
1.导入aop模块;Spring Aop:(spring-aspects)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
2.定义一个业务逻辑类(MathCalculator);
在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)
@Configuration
public class MainConfigOfAop{
}
3、定义一个日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行;
(1).通知方法:
前置通知(@Before):logStart:在目标方法(div)运行之前运行
后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)
返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行
异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行
环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced()
(2). 抽取公共的切入点表达式
切点
@Pointcut("execution(public int com.atguigu.aop.MathCalculator.*(..))")
public void pointCut(){};
①.本类引用
@Before("pointCut()")
②.其他的切面引用
@After("com.atguigu.aop.LogAspects.pointCut()")
不使用切点
@Before("execution(public int com.atguigu.aop.MathCalculator.*(..))")
4、给切面类的目标方法标注何时何地运行(通知注解);
public class LogAspects {
@Pointcut("execution(public int com.atguigu.aop.MathCalculator.*(..))")
public void pointCut(){};
@Before("public int com.atguigu.aop.MathCalculator.div(int,int)")
public void logStart() {
System.out.println("除法运行。。。参数列表是:{}");
}
@After("com.atguigu.aop.LogAspects.pointCut()")
public void logEnd() {
System.out.println("除法结束。。。");
}
@AfterReturning("pointCut()")
public void logReturn() {
System.out.println("除法正常返回。。。运行结果:{}");
}
@AfterThrowing("pointCut()")
public void logException() {
System.out.println("除法异常。。。异常信息:{}");
}
}
5、将切面类和业务逻辑类(目标方法所在类)都加入到容器中;
@Configuration
public class MainConfigOfAop {
//业务逻辑类加入容器中
@Bean
public MathCalculator calculator(){
return new MathCalculator();
}
//切面类加入到容器中
@Bean
public LogAspects logAspects(){
return new LogAspects();
}
}
6、必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
@Aspect
public class LogAspects {}
7.给配置类加@EnableAspectJAutoProxy【开启基于注解的aop模式】
@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAop {}
补充
@Before("execution(public int com.atguigu.aop.MathCalculator.*(..))")
public void logStart(JoinPoint joinPoint) {
//获取目标方法的方法名 :joinPoint.getSignature().getName()
//获取目标方法的参数列表 :Arrays.asList(joinPoint.getArgs())
}
获取目标方法的返回值
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(Object result) {
//目标方法返回值:result
}
获取目标方法的异常
@AfterThrowing(value="pointCut()",throwing="exception")
public void logException(Exception exception) {
//异常:exception
}
注意:JoinPoint一定要出现在参数列表的第一位,要不然要出错
快速使用:使用aop五步
- 1)、导入aop模块;Spring Aop:(spring-aspects)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
- 2)、编写业务逻辑组件
eg
package com.atguigu.aop;
public class MathCalculator {
public int div(int i,int j) {
return i/j;
}
}
- 3)、将业务逻辑组件和切面类都加入到容器中;顺便开启基于注解的aop模式; @EnableAspectJAutoProxy
@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAop {
//业务逻辑类加入容器中
@Bean
public MathCalculator calculator(){
return new MathCalculator();
}
//切面类加入到容器中
@Bean
public LogAspects logAspects(){
return new LogAspects();
}
}
- 4)、告诉Spring哪个是切面类(@Aspect),
在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)
package com.atguigu.aop;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class LogAspects {
@Pointcut("execution(public int com.atguigu.aop.MathCalculator.*(..))")
public void pointCut(){};
// @Before在目标方法之前切入;切入点表达式(指定在那个方法切入)
@Before("execution(public int com.atguigu.aop.MathCalculator.*(..))")
public void logStart(JoinPoint joinPoint) {
System.out.println(joinPoint.getSignature().getName()+"运行。。。参数列表是:{"+Arrays.asList(joinPoint.getArgs())+"}");
}
@After("com.atguigu.aop.LogAspects.pointCut()")
public void logEnd() {
System.out.println("除法结束。。。");
}
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(Object result) {
System.out.println("除法正常返回。。。运行结果:{"+result+"}");
}
@AfterThrowing(value="pointCut()",throwing="exception")
public void logException(Exception exception) {
System.out.println("除法异常。。。异常信息:{"+exception+"}");
}
}
- 5)、测试
package com.atguigu.text;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.atguigu.aop.MathCalculator;
import com.atguigu.config.MainConfigOfAop;
public class IOCTest_Aop {
public static void main(String[] args) {
ApplicationContext applicationContext=new AnnotationConfigApplicationContext(MainConfigOfAop.class);
MathCalculator m=(MathCalculator)applicationContext.getBean(MathCalculator.class);
System.out.println(m.div(9, 3));
}
}