BeanCurrentlyInCreationException异常分析及解决

异常分析

        Spring Boot 出现BeanCurrentlyInCreationException: Error creating bean with name: Requested bean is currently in creation异常是因为出现了两个bean相互依赖。如果 bean A依赖于bean B,而bean B又依赖于bean A,则将产生BeanCurrentlyInCreationException异常。

BEAN A -> BEAN B -> BEAN A  (两个bean循环依赖)

BEAN A -> BEAN B -> BEAN C -> BEAN A  (三个bean循环依赖)

当 spring boot 应用程序加载所有 bean 时,它会尝试自动连接依赖 bean。如果两个 bean 处于循环依赖关系中,则每个 bean 将等待另一个 bean 加载。加载 bean 时会出现死锁。因此,Spring Boot 应用程序将抛出异常。

如果 spring boot 应用程序中的两个或多个bean参与循环依赖,则spring boot应用程序无法在应用程序上下文中加载任何bean,因为每个bean 依赖于另一个bean。Spring boot 无法决定在循环依赖中首先加载哪个bean。因此,在将 bean 加载到应用程序上下文中时,spring boot 会抛出异常。

出现循环依赖的示例:

package com.demo;

public interface Animal {
    String  getName();
}
package com.demo;

import org.springframework.stereotype.Component;

@Component
public class Lion  implements Animal {
    public Lion(Tiger tiger) {

    }

    @Override
    public String getName() {
        return "Lion";
    }
}
package com.demo;

import org.springframework.stereotype.Component;

@Component
public class Tiger  implements Animal {
    public Tiger(Lion lion){

    }

    @Override
    public String getName() {
        return "Tiger";
    }
}

项目启动后会报以下错误:

***************************

APPLICATION FAILED TO START

***************************

Description:

The dependencies of some of the beans in the application context form a cycle:

┌─────┐

|  lion defined in file [D:\project\study\java\springbean-demo\target\classes\com\demo\Lion.class]

↑     ↓

|  tiger defined in file [D:\project\study\java\springbean-demo\target\classes\com\demo\Tiger.class]

└─────┘

解决方案1:

循环依赖是由于编程或架构的问题。遍历属于循环依赖的 bean,考虑重新设计 bean。这将解决异常。组件必须加载到分层依赖模型而不是循环模型中。为了解决这个异常,应该重新设计 bean 的加载顺序。

解决方案2:

循环依赖中的 bean 可以使用 @Autowired 注释加载。@Autowired 注释创建一个 bean 并加载依赖项。这将解决异常。但是,如果 bean 中的方法相互依赖,则会导致异常。

@Component
public class Lion  implements Animal {
    @Autowired
    private Tiger tiger;

    @Override
    public String getName() {
        tiger.getName();
        return "Lion";
    }
}
@Component
public class Tiger  implements Animal {
    @Autowired
    private Lion lion;

    @Override
    public String getName() {
        lion.getName();
        return "Tiger";
    }
}

解决方案3

Spring Boot 应用程序支持 bean 的延迟加载。@Lazy 注释在需要时加载 bean,而不是在开始时加载它。在创建 bean 并将其加载到上下文中后,将注入 bean。首先将创建循环依赖项中的 bean,然后将其他 bean 注入 bean。

@Component
public class Lion  implements Animal {
    public Lion(@Lazy Tiger tiger) {

    }
    
    @Override
    public String getName() {
        return "Lion";
    }
}

@Component
public class Tiger  implements Animal {
    public Tiger(@Lazy Lion lion){

    }

    @Override
    public String getName() {
        return "Tiger";
    }
}

解决方案4

spring boot 注解@PostConstruct 将用于在构造函数方法被调用后执行一个方法。可以使用后构造方法启动循环依赖 bean。Bean 将首先使用构造函数创建,然后将使用带注释的 @PostConstruct 方法创建 bean。

@Component
public class Lion  implements Animal {
    @Autowired
    Tiger tiger;

    @PostConstruct
    public void load() {
        tiger.setLion(this);
    }

    @Override
    public String getName() {
        return "Lion";
    }

    public void setTiger(Tiger tiger) {
        this.tiger = tiger;
    }
}

@Component
public class Tiger  implements Animal {
    @Autowired
    Lion lion;

    @PostConstruct
    public void load() {
        lion.setTiger(this);
    }

    @Override
    public String getName() {
        return "Tiger";
    }

    public void setLion(Lion lion) {
        this.lion = lion;
    }
}

解决方案5

@Autowired 注解可以在 setter 方法中使用。可以使用 @Autowired setter 方法分配 Bean。首先加载 bean,然后调用 setter 方法来自动连接其他 bean。

@Component
public class Lion  implements Animal {
    Tiger tiger;


    @Override
    public String getName() {
        return "Lion";
    }

    @Autowired
    public void setTiger(Tiger tiger) {
        this.tiger = tiger;
    }
}

@Component
public class Tiger  implements Animal {
    Lion lion;


    @Override
    public String getName() {
        return "Tiger";
    }

    @Autowired
    public void setLion(Lion lion) {
        this.lion = lion;
    }
}

翻译自:https://www.yawintutor.com/beancurrentlyincreationexception-error-creating-bean-with-name-requested-bean-is-currently-in-creation/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值