@Async引发的BeanCurrentlyInCreationException

文章讲述了在启用Spring的异步处理注解@EnableAsync后,由于Bean的加载顺序导致的BeanCurrentlyInCreationException异常。问题出在HelloServiceA注入了未完成初始化的AyncTestImpl。解决方案是在HelloServiceA中使用@Lazy注解延迟加载AyncTestImpl。文章还探讨了@Async增强的时机和AOP增强的一般过程。
摘要由CSDN通过智能技术生成

异常出现条件

  1. 开启异步处理注解 @EnableAsync
  2. 代码环境
@Service
public class AyncTestImpl implements AyncTest {
	
	
	@Autowired
	private HelloServiceA helloServiceA;
	
	@Async
	@Override
	public void sayHello() {
		helloServiceA.hello();
	}
}
@Service
public class HelloServiceA {


	@Autowired
	private AyncTest ayncTest;
	
	public void hello(){
		System.out.println("hello A");
	}
	
}
  1. 加载顺序,这里我们得确保Spring首先实例化AyncTestImpl 然后在实例化HelloServiceA。,同一个文件夹下AyncTestImpl 在HelloServiceA 前面默认加载顺序就可以符合。
    在这里插入图片描述
    DefaultListableBeanFactorypreInstantiateSingletons() 方法
    在这里插入图片描述

出现如下异常

警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'ayncTestImpl': Bean with name 'ayncTestImpl' has been injected into other beans [helloServiceA] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.
Exception in thread "main" org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'ayncTestImpl': Bean with name 'ayncTestImpl' has been injected into other beans [helloServiceA] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:682)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:540)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:369)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:283)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:367)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:905)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:943)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:591)
	at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:108)
	at com.demo.Entrance.main(Entrance.java:41)

解释:: helloServiceA 注入的ayncTestImpl 不是最终的版本。我们知道ayncTestImpl的方法是需要进行异步执行,正常ayncTestImpl对象是没有这种功能的,要添加这种功能需要对ayncTestImpl对象进行代理,所以Spring有处理器对ayncTestImpl对象进行动态代理,使之具有异步方法功能。出现这个异常就是说helloServiceA 注入的ayncTestImpl的原始对象, 而Spring容器最终的aynnTestImpl的对象是进行代理之后具有异步功能的代理对象

解决方法

让Spring容器先完全的加载ayncTestImpl对象,容器注入ayncTestImpl代理对象之后再去,即可以在ayncTestImpl的注入对象加入@Lazy注解。

@Service
public class AyncTestImpl implements AyncTest {
	
	
	@Autowired
	@Lazy
	private HelloServiceA helloServiceA;
	
	@Async
	@Override
	public void sayHello() {
		helloServiceA.hello();
	}
}

原理探究

设置Debug断点,我们直接看ayncTestImpl的Bean生命周期过程就行。
在这里插入图片描述

这里就不就Debug了,建议自己去Debug, 这里只总结出一个流程图,更容易接收

@Async增强时机与一般AOP增强时机的过程

在这里插入图片描述

总结

到这里,Async为什么会引发BeanCurrentlyInCreationException 就结束了,接着笔者还会出一篇博文, 探究@aync的增强原理,为什么我们开启了 @EnableAsync 注解,然后在方法上使用 @Async 就可以使用异步功能,以及如果异步方法出现了异常,Spring Async又提供了怎样获取异常处理扩展点呢?

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
@Async方法是Spring框架中的一种特殊注解,用于实现异步方法调用。通过在方法上添加@Async注解,可以告诉Spring容器该方法应该在单独的线程中执行,而不会阻塞当前线程的执行。\[1\] 要使用@Async方法调用,需要按照以下步骤进行操作: 1. 在启动类上添加@EnableAsync注解,以启用异步功能。\[2\] 2. 在需要异步执行的方法上添加@Async注解。这样,当调用该方法时,Spring会自动将其放入线程池中执行,并返回一个Future对象,用于获取异步方法的执行结果。\[3\] 例如,假设我们有一个名为doSomething的方法需要异步执行,我们可以在方法上添加@Async注解,如下所示: ```java @Async public Future<String> doSomething() { // 异步执行的逻辑 return new AsyncResult<>("异步方法执行结果"); } ``` 在调用doSomething方法时,它将在单独的线程中执行,并返回一个Future对象。我们可以使用该对象来获取异步方法的执行结果,如下所示: ```java Future<String> futureResult = doSomething(); String result = futureResult.get(); // 获取异步方法的执行结果 ``` 通过使用@Async方法调用,我们可以实现并发执行任务,提高系统的响应性能和吞吐量。同时,它也可以帮助我们处理那些不需要立即返回结果的耗时操作,提高系统的并发处理能力。 #### 引用[.reference_title] - *1* *3* [在Spring中使用Future对象调用Async方法调用](https://blog.csdn.net/dnc8371/article/details/106705454)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Spring中使用@Async异步调用方法](https://blog.csdn.net/qq_34178998/article/details/95939425)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值