解决非Spring Bean访问Spring Bean的问题:实用指南
  wTh0bPPZpNwc 2024年08月07日 40 0

在非SpringBean类里获取SpringBean,会是什么情况?

case1

下面这段代码中,PlainClass 表示一个普通Java类:

public class PlainClass {   public void foo1() {  TheOtherBean bean = SpringContextUtils.getBean(TheOtherBean.class);  System.out.println(bean);  } }   import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component;  @Component public class SpringContextUtils implements ApplicationContextAware {  /**  * Spring容器上下文对象实例  */  private ApplicationContext applicationContext;   @Override  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {  this.applicationContext = applicationContext;  }   public <T> T getBean(Class<T> clazz) {  return applicationContext.getBean(clazz);  }  }

我们在SpringBean里执行 PlainClass#foo1 是没问题的。

而在非SpringBean中执行 PlainClass#foo1,会抛空指针异常,这是因为在这种情况下,SpringContextUtils未被Spring容器管理,无法获取到applicationContext对象。

java.lang.NullPointerException  at jstudy.redislimit.SpringContextUtils.getBean(SpringContextUtils.java:30)  at jstudy.beantest.PlainClass.foo1(PlainClass.java:12)  at jstudy.beantest.BeanTest.test(BeanTest.java:18)

 

 

case2

接着看下面代码中的 PlainClass :

import org.springframework.beans.factory.annotation.Autowired;  public class PlainClass {  @Autowired  private TheOtherBean theOtherBean;   public void foo2() {  System.out.println(theOtherBean);  } }   import org.springframework.stereotype.Component;  @Component public class TheOtherBean { }

此时,在SpringBean 里执行 PlainClass#foo2 , 输出结果是什么?

 

 

是null。也就是说 theOtherBean 对象是null。为什么? 因为Spring启动时,程序先加载的是 PlainClass 类(它不受Spring管理),而此时`TheOtherBean`尚未被注入容器里,自动装配失败,注入的`TheOtherBean`为null。

当然, 我们通常在项目中不会写这种烂代码来“博人眼球”。

 

细心的同学可以发现,IDE会在 PlainClass 这个非SpringBean里使用的@Autowired注解上给出警告,提示"Autowired members must be defined in valid Spring bean (@Component|@Service|...)",提醒开发者合适地定义Bean以避免这类问题。

 image.png

 

另外,在非SpringBean 里执行 PlainClass#foo2呢?依然是null。

 

 

附上我所使用的测试类代码

package jstudy.beantest;  import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner;  @SpringBootTest @RunWith(SpringRunner.class) public class BeanTest {  @Test  public void test() {  new PlainClass().foo2();  } }

该测试类`BeanTest`在SpringBoot环境下运行。注释掉 @SpringBootTest 和 @RunWith(SpringRunner.class)后,`BeanTest`就是一个非SpringBean(普通Java类)了。

 

 

总结

在非SpringBean类中直接获取SpringBean可能会引发问题,例如上面案例里提到的空指针和自动装配失败。为避免这些问题,建议将需要访问Spring Bean的类也注册为Spring Bean,以确保依赖关系得到正确管理。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2024年08月07日 0

暂无评论

推荐阅读
  VGxawBTN4xmE   2天前   19   0   0 Java
  FHUfYd9S4EP5   4天前   29   0   0 Java
  u8s65Xl4dX8N   7小时前   9   0   0 Java
  qCe06rFCa8NK   7小时前   13   0   0 Java
  ZTo294hNoDcA   4天前   29   0   0 Java
  FHUfYd9S4EP5   4天前   24   0   0 Java
wTh0bPPZpNwc