做網(wǎng)站重慶今天的病毒感染情況
背景
用了spring retry 發(fā)現(xiàn)在有些場景下失效,也讓我想起了之前看spring 事務(wù)時(shí)會有一些場景下失效的這個問題
代碼
接口public interface UserService {public void start() ;public void stop();
}實(shí)現(xiàn)類
@Service
public class UserServiceImpl implements UserService {@Override@Retryable()public void start() {if (1 == 1) {throw new RuntimeException();}}@Overridepublic void stop() {start();}
}
測試
ConfigurableApplicationContext run = SpringApplication.run(K8sDemoApplication.class, args);UserService user = run.getBean(UserService.class);//生效user.start();//失效// user.stop();
測試發(fā)現(xiàn)如果直接調(diào)用start 方法是會生效的
通過stop()方法里面調(diào)用start 方法是會失效的
分析
首先我們知道如果要在一個方法前后加一些todo ,有兩種方法,一種是硬code
還有一種是通過動態(tài)代理的方法,這里通過注解的方法,實(shí)際底層是通過cglib這種代理實(shí)現(xiàn)的,默認(rèn)應(yīng)該是jdk動態(tài)代理的,但是我用arthas分析實(shí)際是用cglib這種形式,這個不重要。
為啥通過代理的,兩種不同的調(diào)用方式會有區(qū)別呢
直接調(diào)用為啥是可以的,因?yàn)閷?shí)際上的調(diào)用對象是生成的動態(tài)代理對象,在方法上進(jìn)行代理的。
我們重點(diǎn)了解下為啥間接調(diào)用失敗。
看下編譯后的代碼
@Service
public class UserServiceImpl implements UserService {public UserServiceImpl() {}public void start() {throw new RuntimeException();}public void stop() {//實(shí)際上調(diào)用start,我們可以發(fā)現(xiàn)是通過this 對是本身這個對象直接調(diào)用的this.start();}
}
總結(jié)
加深了對之前glibc動態(tài)代理的理解