使用main方法启动spring程序
在 spring 框架中,由于对象都交给了 IoC 容器进行管理,那么直接在 main 方法中创建 service 层对象,就会出现空指针异常(NPE)
正确的方式是从 IoC 的容器中取出对象
,再使用对象中的方法或者属性就可以了
核心代码
public static void main(String[] args) {// applicationContext.xml 为 spring 配置文件名ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");// userService 为 IOC 容器中的对象名UserService userService = (UserService) context.getBean("userServiceImpl");// 使用 userService 对象调用方法userService.save(new User(1,"小明"));
}
====================================================
原因分析:
如果使用普通方式创建对象,代码及运行结果如下:
通过控制台打印结果可以看出问题代码出现在 UserServiceImpl.save() 方法在 UserServiceImpl 类的第 22 行,进入 UserServiceImpl 类,代码如下:
通过 Debug 追踪,可以看出 userDao 对象为空。因为 UserDao 是通过 spring 的 IoC 进行对象管理,并且在测试类创建 service 对象时,并未加载 spring 相关配置,所以 userService 对象中的 userDao 属性并未被注入值,故而在调用 userDao 的 save 方法时出现空指针异常。
====================================================
正确示例
稍微细心一点就能发现这是自己想法的逻辑错误,既然用了 spring 的自动注入(前提是有多层依赖),那么就不应该再去手动创建对象。选择手动创建对象就不应该使用 spring 的依赖注入。
public static void main(String[] args) {// applicationContext.xml 为 spring 配置文件名ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");// userService 为 IOC 容器中的对象名UserService userService = (UserService) context.getBean("userServiceImpl");// 使用 userService 对象调用方法userService.save(new User(1,"小明"));
}
通过追踪源码发现 context.getBean() 方法最终来源于 BeanFactory 接口
,并且 getBean() 方法有多种重载形式
,如下:
那么获取 IOC 容器中对象的方式就有多种,如下:
1.对象名获取,返回的是 Object 类型,需要强转
- UserService userService = (UserService) context.getBean(“userServiceImpl”);
2.class获取,返回class对应的对象,不需要强转
- UserService userService = context.getBean(UserServiceImpl.class);
3.对象名和class获取指定对象,不需要强转
- UserService userService = context.getBean(“userServiceImpl”,UserServiceImpl.class);
4.其它略,可根据需要使用