Spring Aop 源码 debug

使用的是spring boot
大致流程 : getSingleton(重点)→singletonFactory.getObject→createBean→doCreateBean(重点)→initizlizeBean→后置处理器(AnnotationAwareAspectjAutoProxyCreator)的处理方法→wrapIfNecessary→createProxy→proxyFactory.getProxy→createAopProxy(重点)

首先是基本配置

pom.xml



    org.springframework.boot
    spring-boot-starter-aop



    org.aspectj
    aspectjrt
    1.6.11


    org.aspectj
    aspectjweaver
    1.6.11


    cglib
    cglib
    2.1


    org.springframework
    spring-aop
    5.1.7.RELEASE

main方法

@RunWith(SpringRunner.class)
@SpringBootTest
@ComponentScan("com.example.demo")
public class DemoApplicationTests {

    @Test
    public void contextLoads() {
    }

    @Test
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(DemoApplicationTests.class);
        UserDao dao = (UserDao) annotationConfigApplicationContext.getBean("dao");
        dao.query();
    }

}

dao 和 daoImpl

public interface UserDao {
    public void query();
}

@Component("dao")
public class UserDaoImpl implements UserDao {
    @Override
    public void query() {
        System.out.println("I want to ask you a question!");
    }
}

切面类

@Component
@Aspect
public class WebLogAspect {

    @Pointcut("execution(* com.example.demo.Dao..*.*(..))")
    public void sayHello() {

    }

    @Before("sayHello()")
    public void doBefore() {
        System.out.println("before : hello");
    }
}

大致的目录(没有标记的是非相关的)
Spring Aop 源码 debug_第1张图片
实现效果
Spring Aop 源码 debug_第2张图片

Debug流程和思想

aop的实现以代理为基础,要么jdk,要么cglib
如果proxyTargetClass为true,cglib;否则如果有接口,jdk;否则cglib

由上面的main方法可得
要么在容器初始化的时候完成代理
要么getBean的时候完成代理

先测试getBean
在第二行打断点
Spring Aop 源码 debug_第3张图片
进入内部
Spring Aop 源码 debug_第4张图片
再进入getBeanFactory().getBean(name)的getBean方法

在这里插入图片描述
进入doGetBean方法
Spring Aop 源码 debug_第5张图片
已经完成代理
在deGetBean方法中的Object sharedInstance = getSingleton(beanName)已经完成代理;于是在该处打上条件断点(这里有个坑,先到了main方法的第二行再启动这个断点,后续有解释)
Spring Aop 源码 debug_第6张图片
进入getSingleton方法
Spring Aop 源码 debug_第7张图片
其中第一行会直接获得代理对象,说明是在容器初始化时完成代理的。
之后的debug有个技巧,我们可以在map.put方法打个断点。
选择第一个,第三个是相关jndi的
Spring Aop 源码 debug_第8张图片
同样的条件断点beanName.equal(“dao”)
Spring Aop 源码 debug_第9张图片
进入这个断点,分析现象,此时是addSingleton方法
已经完成代理,通过左下角的堆栈查找完成代理的方法
Spring Aop 源码 debug_第10张图片
在getSingleton方法打个条件断点
Spring Aop 源码 debug_第11张图片
进入这个方法
这里没有完成代理
Spring Aop 源码 debug_第12张图片
于是在singletonObject = singletonFactory.getObject();打上断点,并进入getObject方法,getObject方法会进入createBean方法
Spring Aop 源码 debug_第13张图片

createBean会在doCreateBean方法完成代理
Spring Aop 源码 debug_第14张图片
进入doCreateBean方法,代理在initializeBean方法中完成
Spring Aop 源码 debug_第15张图片
进入initializeBean方法,代理会通过applyBeanPostProcessorsAfterInitialization(后置处理器相关)方法完成
Spring Aop 源码 debug_第16张图片
进入applyBeanPostProcessorsAfterInitialization方法,这的下标4是跟aspectj相关的,也是在这一步完成代理的
Spring Aop 源码 debug_第17张图片
进入i = 4 的postProcessAfterInitialization方法
Spring Aop 源码 debug_第18张图片再进入wrapIfNecessary方法
Spring Aop 源码 debug_第19张图片
再进入createProxy方法
Spring Aop 源码 debug_第20张图片
再进入proxyFroxy.getProxy方法
在这里插入图片描述
getProxy方法会进入createAopProxy方法
Spring Aop 源码 debug_第21张图片
最后的就是这creaetAopProxy方法
如果proxytargetclass = true,使用cglib

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
   if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
      Class targetClass = config.getTargetClass();
      if (targetClass == null) {
         throw new AopConfigException("TargetSource cannot determine target class: " +
               "Either an interface or a target is required for proxy creation.");
      }
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
         return new JdkDynamicAopProxy(config);
      }
      return new ObjenesisCglibAopProxy(config);
   }
   else {
      return new JdkDynamicAopProxy(config);
   }
}

到此,我要说的基本没了
上面我说
在deGetBean方法中的Object sharedInstance = getSingleton(beanName)已经完成代理;于是在该处打上条件断点(这里有个坑,先到了main方法的第二行再启动这个断点,后续有解释)
是因为在容器初始化时完成代理,那么如果直接在getSingleton打了断点会先执行getSingleton方法,在执行main方法的第二行

你可能感兴趣的:(Spring,aop)