簡體   English   中英

Spring @Autowired 不能在抽象超級 class 上使用最終方法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM