背景
用了spring retry 发现在有些场景下失效,也让我想起了之前看spring 事务时会有一些场景下失效的这个问题
代码
接口
public interface UserService {
public void start() ;
public void stop();
}
实现类
@Service
public class UserServiceImpl implements UserService {
@Override
@Retryable()
public void start() {
if (1 == 1) {
throw new RuntimeException();
}
}
@Override
public void stop() {
start();
}
}
测试
ConfigurableApplicationContext run = SpringApplication.run(K8sDemoApplication.class, args);
UserService user = run.getBean(UserService.class);
//生效
user.start();
//失效
// user.stop();
测试发现如果直接调用start 方法是会生效的
通过stop()方法里面调用start 方法是会失效的
分析
首先我们知道如果要在一个方法前后加一些todo ,有两种方法,一种是硬code
还有一种是通过动态代理的方法,这里通过注解的方法,实际底层是通过cglib这种代理实现的,默认应该是jdk动态代理的,但是我用arthas分析实际是用cglib这种形式,这个不重要。
为啥通过代理的,两种不同的调用方式会有区别呢
直接调用为啥是可以的,因为实际上的调用对象是生成的动态代理对象,在方法上进行代理的。
我们重点了解下为啥间接调用失败。
看下编译后的代码
@Service
public class UserServiceImpl implements UserService {
public UserServiceImpl() {
}
public void start() {
throw new RuntimeException();
}
public void stop() {
//实际上调用start,我们可以发现是通过this 对是本身这个对象直接调用的
this.start();
}
}
总结
加深了对之前glibc动态代理的理解