1.切面类
@Aspect 告诉Spring当前类是一个切面类
通知方法:
-
logStart (JoinPoint joinPoint):在目标方法(div)运行之前运行, JoinPoint 作为参数 拿到目标方法的参数前置通知( @Before ("pointCut()") ):
-
logEnd (JoinPoint joinPoint):在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)后置通知 ( @After("com.atguigu.aop.LogAspects.pointCut()") ):
-
logReturn (JoinPoint joinPoint,Object result):在目标方法(div)正常返回之后运行,result作为接收目标方法执行结束之后返回的结果返回通知( @AfterReturning (value="pointCut()",returning="result") ):
-
logException (JoinPoint joinPoint,Exception exception) :在目标方法(div)出现异常以后运行, exception作为接收目标方法执行异常之后抛出的异常异常通知(@AfterThrowing( value="pointCut()",throwing="exception" ) ):
-
环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
@Aspect
public class LogAspects {
//抽取公共的切入点表达式
//1、本类引用----(public int com.atguigu.aop.MathCalculator.*(..))
//2、其他的切面引用---("execution(public int com.atguigu.aop.MathCalculator.*(..))")
@Pointcut("execution(public int com.atguigu.aop.MathCalculator.*(..))")
public void pointCut(){};
//@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
@Before("pointCut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+Arrays.asList(args)+"}");
}
@After("com.atguigu.aop.LogAspects.pointCut()")
public void logEnd(JoinPoint joinPoint){
System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
}
//JoinPoint一定要出现在参数表的第一位,否则(Object result, JoinPoint joinPoint)格式会报错
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
}
@AfterThrowing(value="pointCut()",throwing="exception")
public void logException(JoinPoint joinPoint,Exception exception){
System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息:{"+exception+"}");
}
}
2. 业务逻辑类(MathCalculator)
- 在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)
- 根据 div(int i,int j) 方法 运行到哪里动态感知
public class MathCalculator {
public int div(int i,int j){
System.out.println("MathCalculator...div...");
return i/j;
}
}
3. Config配置文件
- 将切面类和业务逻辑类(目标方法所在类)都加入到容器
- 并且 在切面类上加上 @Aspect 注解 表明哪一个才是切面类
- 在Config配置文件 上加上 @EnableAspectJAutoProxy注解 表明开启基于注解的aop模式
@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAOP {
//业务逻辑类加入容器中
@Bean
public MathCalculator calculator(){
return new MathCalculator();
}
//切面类加入到容器中
@Bean
public LogAspects logAspects(){
return new LogAspects();
}
}
4. test测试文件
不要自己创建 MathCalculator目标 对象 ,因为自己创建的目标对象没有放进容器里面,需要用 applicationContext.getBean(MathCalculator.class) 取出容器内的目标对象
public class IOCTest_AOP {
@Test
public void test01(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
//1、不要自己创建对象
// MathCalculator mathCalculator = new MathCalculator();
// mathCalculator.div(1, 1);
MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
mathCalculator.div(1, 1);
applicationContext.close();
}
}
5. test测试结果
- div(1, 1) 的结果
- div(1, 0) 的结果