Sping-AOP注解开发,后面有彩蛋哦

微信公众号:Java修炼手册
关注可获取3T免费学习资料,助你从0到1;

AOP注解开发
AOP代码实现(执行计算前后输入输出目标代码)
1 定义一个业务逻辑类(MathCalculator);在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常)

1  public class MathCalculator {
2      public int div(int i,int j){
3      System.out.println("MathCalculator...div...");
4           return i/j;  
5    }
6}
2 定义一个日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行;

```java
1@Aspect
 2public class LogAspects {
 3
 4    //抽取公共的切入点表达式
 5    //1、本类引用
 6    //2、其他的切面引用
 7    @Pointcut("execution(public int com.atguigu.aop.MathCalculator.*(..))")
 8    public void pointCut(){};
 9
10    //@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
11    //1使用引入切点方法
12    //joinPoint:用获取方法信息
13    @Before("pointCut()")
14    public void logStart(JoinPoint joinPoint){
15        Object[] args = joinPoint.getArgs();
16        System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+Arrays.asList(args)+"}");
17    }
18    //2使用引用外部切点类的方法
19    @After("com.atguigu.aop.LogAspects.pointCut()")
20    public void logEnd(JoinPoint joinPoint){
21        System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
22    }
23
24    //JoinPoint一定要出现在参数表的第一位
25    @AfterReturning(value="pointCut()",returning="result")
26    public void logReturn(JoinPoint joinPoint,Object result){
27        System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
28    }
29    //joinPoint必须在返回值前面!!
30    @AfterThrowing(value="pointCut()",throwing="exception")
31    public void logException(JoinPoint joinPoint,Exception exception){
32        System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息:{"+exception+"}");
33    }
34}

通知方法:

@Aspect声明这是一个切面类

前置通知(@Before):logStart:在目标方法(div)运行之前运行

后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)

返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行

异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行

环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())

3 将切面类和业务逻辑类(目标方法所在类)都加入到容器中;

 1@EnableAspectJAutoProxy
 2@Configuration
 3public class MainConfigOfAOP {
 4
 5    //业务逻辑类加入容器中
 6    @Bean
 7    public MathCalculator calculator(){
 8        return new MathCalculator();
 9    }
10
11    //切面类加入到容器中
12    @Bean
13    public LogAspects logAspects(){
14        return new LogAspects();
15    }
16}

给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】!!!

4 测试

1public class IOCTest_AOP {
 2
 3    @Test
 4    public void test01(){
 5        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
 6
 7        //1、不要自己创建对象
 8//        MathCalculator mathCalculator = new MathCalculator();
 9//        mathCalculator.div(1, 1);
10        MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
11
12        mathCalculator.div(1, 0);
13
14        applicationContext.close();
15    }
16
17}

只有在spring容器内的对象才能使用aop功能,所以使用的时候不能自己new一个对象,而是从容器获取!!!

运行结果:

1div运行。。。@Before:参数列表是: {[1, 1]} 
2MathCalculator. . .div. . .
3div结束。。。@After
4div正常返回。。。@AfterReturning:运行结果: {1}

执行过程及源码解析
平时看注解的源码有一个小窍门,跟着源码进去会发现,该注解会实现了什么类,或者注入了某些组件,把注入组件的功能,跟注入的时间点搞清楚了,那么该功能的逻辑就会变得清晰

@EnableAspectJAutoProxy是什么?
@Import(AspectJAutoProxyRegistrar.class):给容器中导入AspectJAutoProxyRegistrar

利用AspectJAutoProxyRegistrar自定义给容器中注册bean;BeanDefinetion

internalAutoProxyCreator=AnnotationAwareAspectJAutoProxyCreator

给容器中注册一个AnnotationAwareAspectJAutoProxyCreator;

跟着继承树:
AnnotationAwareAspectJAutoProxyCreator->AnnotationAwareAspectJAutoProxyCreator->AspectJAwareAdvisorAutoProxyCreator->AbstractAdvisorAutoProxyCreator->AbstractAutoProxyCreator

通过他的实现可以发现,它是一个后置处理器,并且也是factoryawrae接口的实现类
AnnotationAwareAspectJAutoProxyCreator注册过程

最后老规矩的总结一下(也相当重要!)
@EnableAspectJAutoProxy 开启AOP功能

@EnableAspectJAutoProxy 会给容器中注册一个组件
AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator是一个后置处理器;

容器的创建流程:

registerBeanPostProcessors()注册后置处理器;创建AnnotationAwareAspectJAutoProxyCreator对象

finishBeanFactoryInitialization()初始化剩下的单实例bean

组件创建完之后,判断组件是否需要增强

执行目标方法:

代理对象执行目标方法

CglibAopProxy.intercept();

正常的执行顺序:前置通知-》目标方法-》后置通知-》返回通知

出现异常时:前置通知-》目标方法-》后置通知-》异常通知

包括但不限于:分布式架构、高可扩展、高性能、高并发、Jvm性能调优、Spring,MyBatis,Nginx源码分析,Redis,ActiveMQ、Mycat、Netty、Kafka、Mysql、Zookeeper、Tomcat、Docker、Dubbo、Nginx等多个知识点高级进阶干货面试题集,简历模板等三千多G资料包,关注回复DD无套路免费领取,助您从0到1
在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值