[英]Spring @Autowired not working with final method on abstract super class
我有一個帶有自動裝配字段和最終方法的抽象超級 class。 此外,還有一個具體的子 class,其方法調用超級 class 上的最終方法。
摘要超級class:
public abstract class AbstractSuper {
@Autowired
protected AuthenticationService authenticationService;
@Autowired
protected JobRepository jobRepository;
public final void startOnSuper() {
test();
}
private void test() {
assert authenticationService != null;
assert jobRepository != null;
}
}
具體實施:
@Component
@RequiredArgsConstructor
public class ConcreteImpl extends AbstractSuper {
private final PersonService personService;
public void startOnImpl() {
super.startOnSuper();
}
}
JUnit:
@Autowired
private ConcreteImpl concrete;
@Test
public void startOnImpl() {
concrete.startOnImpl();
}
@Test
public void startOnSuper() {
concrete.startOnSuper();
}
為什么 startOnImpl 測試有效而 startOnSuper 測試失敗? 為什么我是從子 class 還是從 class 外部調用方法很重要? object的state不應該一樣嗎?
startOnSuper
方法失敗正是因為它具有final
修飾符,而startOnImpl
方法中不存在該修飾符。 調用concrete.startOnImpl();
和concrete.startOnSuper();
在您的測試 class 中不要直接調用 class 實例,而是動態創建的代理。 調用super.startOnSuper();
,在ConcreteImpl#startOnImpl
里面,並不是通過代理go(其實在進入這個方法之前就已經通過了)而是調用了實例本身的方法,所以不會報錯。
這里要理解的關鍵是 Main class 的 main(..) 方法中的客戶端代碼有對代理的引用。 這意味着對 object 引用的方法調用是對代理的調用。 因此,代理可以委托給與該特定方法調用相關的所有攔截器(建議)。 但是,一旦調用最終到達目標 object(本例中的 SimplePojo 引用),它可能對自身進行的任何方法調用,例如 this.bar() 或 this.foo(),都將被調用這個參考,而不是代理。 第 5.8.1 節
在這種情況下,基於 class(基於類的代理)創建了一個代理,這意味着它的工作方式有一些規則,包括不將最終修改應用於公共或受保護的方法(將通過代理訪問) .
這個代理是一個在運行時動態創建的包裝器,需要覆蓋所有可訪問的方法,這樣它們就不會被直接調用,而是始終在代理本身的控制模式中。 如果方法是 final 的,它不能被覆蓋,這將導致意外的行為。
刪除最終修飾符。
但這也取決於您在項目中使用的設計,我不記得有任何其他實用的替代方案。
您可以在以下鏈接中閱讀有關它的更多信息:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.