深挖Spring Aop 底层实现(一)

713 阅读2分钟

本文可任意转载,转载时请保留作者 Zevi@掘金署名及文章出处juejin.cn/post/684490…

前言

Spring Aop 底层是由Java 动态代理和 cglib 实现的,但是我们会有一些问题:

  • Spring Aop默认使用哪种技术实现Aop?
  • 什么情况下使用Java动态代理?什么情况下使用cglib呢?
好的,我们现在就带着这2个问题开始在Spring 源码里寻找答案。

开始

准备

首先我们写个简单的Spring Aop的环境

依赖的包:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.8.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.0</version>
</dependency>

Spring配置类 AppConfig:

@Configuration
@ComponentScan(basePackages = "com.dahafo")
@EnableAspectJAutoProxy
public class AppConfig {

}

Aop处理类:

@Aspect
@Component
public class AppAspect {

    //定义一个切点
    @Pointcut("execution(* com.dahafo.dao..*.*(..))")
    public void pointCut(){

    }

    @After("pointCut()")
    public void after(){
        System.out.println("aspect---after---");
    }
    
}

dao层接口

public interface Dao {

    public void save();
}

当然需要一个dao 层的方法,HelloDao:

@Component
public class HelloDao implements Dao{

    public void save() {
        System.out.println("dao---save---");
    }
}

好了,准备代码差不多了,我们再写一个main方法启动,

public class Test {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context= new AnnotationConfigApplicationContext(AppConfig.class);
        context.start();
        Dao dao=context.getBean(Dao.class);
        dao.save();
    }
}

先看下效果,控制台成功打印

dao---save---
aspect---after---

说明我们写的aop 能运行成功

开始调试

打断点在Dao dao=context.getBean(Dao.class)上,Debug启动,进入getBean(Dao.class)方法,走到AbstractApplicationContext#getBean(java.lang.Class<T>)方法的return getBeanFactory().getBean(requiredType),进入这段代码执行。
第一个进入的是getBeanFactory()方法,直接走完,回到return getBeanFactory().getBean(requiredType) ,再次进入,再进入DefaultListableBeanFactory#getBean(java.lang.Class<T>, java.lang.Object...)方法。
进入这段代码NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);,走到return new NamedBeanHolder<>(beanName, getBean(beanName, requiredType, args)),再进入,再进入到AbstractBeanFactory#doGetBean方法,走到Object sharedInstance = getSingleton(beanName)这一行,进入,再进入。
到了DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)方法,我们看第一行Object singletonObject = this.singletonObjects.get(beanName)this.singletonObjects,是一个 ConcurrentHashMap,它里面保存了很多类,我们可以从里面找到key为helloDao的类,我们往下走一步,可以看到singletonObject有值了

这个类是我们的HelloDao经过jdk动态代理生成的类,至此,我们已经可以找到spring从哪里拿到了我们代理后的类,但是,我们怎么知道这个类是怎么生成的呢?我们上面2个问题还是没有答案。

预知后事如何,请听下回分解,深挖Spring Aop 底层实现(二)待续

本文可任意转载,转载时请保留作者 Zevi@掘金署名及文章出处juejin.cn/post/684490…