Lombok使用@Data註解當循環依賴時調用hashcode導致StackOverflowError棧溢出的問題

我們知道spring容器會提前暴露剛彎沉構造器注入但未完成其他步驟(如setter注入)的bean,通過提前暴露一個單例工廠方法,從而使其他bean可以引用到該bean,這樣可以解決單例作用域在setter注入循環依賴的問題,但是在測試過程中,缺出現了棧溢出的問題:

通過xml配置簡單配置兩個bean:

@Data
public class TestA {

    private TestB testB;
}


@Data
public class TestB {

    private TestA testA;
}
<bean id="testA" class="pres.zj.testspring.TestA">
    <property name="testB" ref="testB"></property>
</bean>
<bean id="testB" class="pres.zj.testspring.TestB">
    <property name="testA" ref="testA"></property>
</bean>

測試:

public static void main(String[] args) {
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("bean.xml", MyTest.class));
        TestA testA = (TestA) beanFactory.getBean("testA");
        System.out.println(testA.hashCode());
        System.out.println(testA.getTestB().getTestA().hashCode());
    }

結果出現異常:

Exception in thread "main" java.lang.StackOverflowError
    at pres.zj.testspring.TestB.hashCode(TestB.java:9)
    at pres.zj.testspring.TestA.hashCode(TestA.java:9)
    at pres.zj.testspring.TestB.hashCode(TestB.java:9)
    at pres.zj.testspring.TestA.hashCode(TestA.java:9)

其實原因就出在@data註解上,通過反編譯文件,看到lombok重寫的hashcode方法:

public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $testB = this.getTestB();
        int result = result * 59 + ($testB == null ? 43 : $testB.hashCode());
        return result;
    }

TestA在計算hashcode時候調用了TestB類的hashcode方法,同理,TestB在計算hashcode的時候又調用了TestA的hashcode方法,於是便無限遞歸了。

解決方法:使用@Setter和@Getter代替@Data

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章