办理非Spring Bean访问Spring Bean的题目:实用指南

打印 上一主题 下一主题

主题 835|帖子 835|积分 2505

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

下面这段代码中,PlainClass 表示一个平凡Java类:
  1. public class PlainClass {
  2.     public void foo1() {
  3.         TheOtherBean bean = SpringContextUtils.getBean(TheOtherBean.class);
  4.         System.out.println(bean);
  5.     }
  6. }
  7. import org.springframework.beans.BeansException;
  8. import org.springframework.context.ApplicationContext;
  9. import org.springframework.context.ApplicationContextAware;
  10. import org.springframework.stereotype.Component;
  11. @Component
  12. public class SpringContextUtils implements ApplicationContextAware {
  13.     /**
  14.      * Spring容器上下文对象实例
  15.      */
  16.     private ApplicationContext applicationContext;
  17.     @Override
  18.     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  19.         this.applicationContext = applicationContext;
  20.     }
  21.     public <T> T getBean(Class<T> clazz) {
  22.         return applicationContext.getBean(clazz);
  23.     }
  24. }
复制代码
我们在SpringBean里实行 PlainClass#foo1 是没题目的。
而在非SpringBean中实行 PlainClass#foo1,会抛空指针异常,这是因为在这种情况下,SpringContextUtils未被Spring容器管理,无法获取到applicationContext对象。
  1. java.lang.NullPointerException
  2.     at jstudy.redislimit.SpringContextUtils.getBean(SpringContextUtils.java:30)
  3.     at jstudy.beantest.PlainClass.foo1(PlainClass.java:12)
  4.     at jstudy.beantest.BeanTest.test(BeanTest.java:18)
复制代码
 
 
case2

接着看下面代码中的 PlainClass :
  1. import org.springframework.beans.factory.annotation.Autowired;
  2. public class PlainClass {
  3.     @Autowired
  4.     private TheOtherBean theOtherBean;
  5.     public void foo2() {
  6.         System.out.println(theOtherBean);
  7.     }
  8. }
  9. import org.springframework.stereotype.Component;
  10. @Component
  11. public class TheOtherBean {
  12. }
复制代码
此时,在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以避免这类题目。
 

 
别的,在非SpringBean 里实行 PlainClass#foo2呢?依然是null。
 
 
附上我所使用的测试类代码
  1. package jstudy.beantest;
  2. import org.junit.Test;
  3. import org.junit.runner.RunWith;
  4. import org.springframework.boot.test.context.SpringBootTest;
  5. import org.springframework.test.context.junit4.SpringRunner;
  6. @SpringBootTest
  7. @RunWith(SpringRunner.class)
  8. public class BeanTest {
  9.     @Test
  10.     public void test() {
  11.         new PlainClass().foo2();
  12.     }
  13. }
复制代码
该测试类`BeanTest`在SpringBoot情况下运行。解释掉 @SpringBootTest 和 @RunWith(SpringRunner.class)后,`BeanTest`就是一个非SpringBean(平凡Java类)了。
 
 
总结

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

曹旭辉

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表