【Java】使用@Value @Reource或@Autowire依赖 (值) 注入时出现NPE的排查方法

首先想说明的是,@Value @Resource和@Autowire虽然都是用于依赖注入的Annotation,但是二者是有区别的。

    1 Resource不依赖于Spring,后者相反,因此为了减少以来,尽量使用Resource;

    2 Resource是优先按照变量名称匹配的,也可用@Resource(name="")指定要注入的变量名。Autowire则是优先按类型匹配,配合@Qualifier也可指定变量名。

    3 不存在灵异事件!不存在灵异事件!不存在灵异事件!重要的事说三遍。如果出现了NullPointerException,那一定是代码写错了。

 

当出现被注入的变量被调用时抛出NPE,按照如下的经验排查:

0 Spring的xml配置文件是否都包含在classpath(resources、webapp甚至java都可)中,如果有多个xml文件,include的层次关系是否正确。

1 确定类所在的包是否被Spring扫描到。检查配置文件中是否有:

    <context:annotation-config />
    <context:component-scan base-package="me.xxx" />
    <context:component-scan base-package="me.yyy" />

2 检查Bean是否有重复定义。

3 对于静态的依赖,要在其setter方法上加@Resource,目的是欺瞒Spring向一个静态变量进行注入。

<bean id="classType" class="....ClassType" />

static
ClassType classType; @Resource public void setClassType(ClassType classType) { XXX.cXXXlassType = classType; }

4 如果是在测试用例中使用@Resource时出现NPE,则考虑是不是Bean根本没有在applicationContext中创建。

可以用下面的方法写测试用例,以避免对大量的字段进行初始化(需要junit 4.9以上的版本):

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/spring-XXX.xml"})
public class BaseTest extends AbstractJUnit4SpringContextTests {
    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
         // add whatever you like.
    }
}

public class XXXXTest extends BaseTest {...}

 当然如果明确地知道单个测试用例只需用到哪些上下文,也可以把这段写在测试用例XXXTest本身,避免每次都要加载整个上下文,导致重量级的用例。

5 如果要检查上下文是否正常创建,或者某个Bean是否在上下文中,可以直接用@Resource调出名为“applicationContext”的全局上下文。

 

 

posted @ 2016-04-22 17:32  chng  阅读(1064)  评论(0编辑  收藏  举报
BackToTop