Spring Aop源码调试

本文围绕 Spring AOP 面向切面编程展开,通过项目 demo 进行源码调试。使用注解方式,在调试中发现 service 对象被 Aop CGLIB 代理,通过二分查找法排查 jvm 运行栈,确定 Spring AOP 创建代理对象的时机,最后完成源码调试,并给出官网及其他参考资料。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringAOP 面向切面编程(Aspect Oriented Programming)

aop效果:

项目demo:

代码:

import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class AppConfig {

    @Pointcut("execution(* com.spring.demo.service.*.*(..))")
    public void businessService() {}

    @Before(value = "businessService()")
    public void doBefore() {
        System.out.println("----------------- doBefore -----------------");
    }
    @AfterReturning(value = "businessService()")
    public void doAfterReturning() {
        System.out.println("----------------- doAfterReturning -----------------");
    }
    @After(value = "businessService()")
    public void doAfter() {
        System.out.println("----------------- doAfter -----------------");
    }
}
import com.spring.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @description:
 * @author: yz
 * @create: 2019/5/27 15:33
 */
@RestController
public class TestController {

    @Autowired
    UserService userService;

    @RequestMapping("/test")
    public String test(){
        return userService.query();
    }
}
public interface UserService {
    String query();
}
@Service("userService")
public class UserServiceImpl implements UserService {
    @Override
    public String query() {
        System.out.println("------------ yz ------------");
        return "------------ yz ------------";
    }
}
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

请求url:http://localhost:8080/test

源码调试,编写main方法,使用注解方式:

import com.spring.demo.service.UserService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

/**
 * @description:
 * @author: yz
 * @create: 2019/5/27 15:23
 */
@ComponentScan("com.spring.demo")
public class Main {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Main.class);
        UserService userService = applicationContext.getBean(UserService.class);
//        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.query();
    }
}

断点发现,拿到的service对象已经是被Aop CGLIB代理过的对象,main方法打印aop代理service后的信息:

被代理时间可能发生在第一步,也可能发生在第二步,此时假设发生在第二步,断点打在getBean进行跟踪:

发现singletonObjects 是个map

既然singletonObjects有get,那么就有put,此时切入点查找this.singletonObjects.put

用2分查找法排查jvm运行栈,具体在哪一个方法userService被aop代理。

注意:此时还没有执行到UserService userService = applicationContext.getBean(UserService.class);

也就是说spring aop创建代理代理对象是在第一步执行的:

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Main.class);

我们将断点打在doGetBean的getSingleton方法,加条件断点,这是个Lambda表达式

重新运行,进入getSingleton方法

至此Spring Aop源码调试完毕。

Spring Aop官网资料:

https://docs.spring.io/spring/docs/5.2.0.BUILD-SNAPSHOT/spring-framework-reference/core.html#aop

其他资料:https://blog.youkuaiyun.com/u010890358/article/details/80640433

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值