通过new方式得到的普通类获取spring的bean对象

╰半橙微兮° 2022-05-13 08:28 612阅读 0赞

在Spring框架中,我们通常将bean对象交给spring容器,然后使用注解的方式引入,不用手动的去创建类。

如在service类上加@Service,在controller类上加@Controller,通过@Autowired注解引入调用bean对象的方法

service类:

  1. public interface ISupplierService {
  2. public SupplierBase getSupplier(Long id);
  3. }
  4. @Service
  5. public class SupplierServiceImpl implements ISupplierService {
  6. @Autowired
  7. private ISupplierDao supplierDao;
  8. @Override
  9. public SupplierBase getSupplier(Long id) {
  10. return supplierDao.getSupplier(id);
  11. }
  12. }

controller类:

  1. @Controller
  2. @RequestMapping(value="/supplier")
  3. public class SupplierManagementAction{
  4. @Autowired
  5. private ISupplierService service;
  6. @RequestMapping(value="/supplierIndex")
  7. public String supplierIndex(ModelMap modelMap, Long supplierId) throws Exception{
  8. if(null!=id && id.trim().length()>0 ){
  9. SupplierBase supplierBase = service.getSupplierByRegionType(supplierId);
  10. if(null!=supplierBase){
  11. modelMap.put("supplierBase", supplierBase);
  12. }
  13. }
  14. return "supplier/supplierIndex";
  15. }
  16. }

但是,最近在项目中遇到这种情况:
导出excel数据,首先根据条件查询符合要求的数据,然后在Controller中使用new的方式得到普通类,最后将数据传到普通类中,专门处理excel构建。部分代码如下:

controller类:

  1. @Controller
  2. @RequestMapping(value="/sproduct")
  3. public class SupplierProductManagementAction{
  4. @RequestMapping(value="/exportExcel", method=RequestMethod.POST)
  5. public ModelAndView exportExcel(@ModelAttribute PmSupplierBase productFromBean,ModelMap model,HttpSession session) {
  6. int pageIndex = 1;
  7. if(null!=productFromBean.getBatchNum()){
  8. pageIndex = productFromBean.getBatchNum().intValue();
  9. }
  10. productFromBean.setBusinessType(super.getBusinessType());
  11. productFromBean.setExportExcel(true);
  12. Page<PmSupplierBase> supplierList = productService.queryPmSupplierProduct(productFromBean, excelMaxHang, pageIndex,getBty());
  13. SProductExportExcel productExcel = new SProductExportExcel();
  14. return new ModelAndView(productExcel,"pmData",supplierList.getResults());
  15. }
  16. }

用于处理生成excel的普通类:

  1. public class SProductExportExcel extends AbstractExcelView {
  2. @Override
  3. protected void buildExcelDocument(Map<String, Object> model,
  4. HSSFWorkbook workbook, HttpServletRequest request,
  5. HttpServletResponse response) throws Exception {
  6. Date currDate = new Date();
  7. HSSFSheet sheet = workbook.createSheet("PSupplier导出(" + DateUtils.dateFormatToString(currDate, "yyyy-MM-dd") + ")");
  8. HSSFRow sheetRow = sheet.createRow(0);
  9. int index = 0;
  10. HSSFCellStyle colorStyle = workbook.createCellStyle();
  11. colorStyle.setFillForegroundColor(HSSFColor.YELLOW.index);
  12. colorStyle.setFillBackgroundColor(HSSFColor.YELLOW.index);
  13. colorStyle.setFillPattern(HSSFColor.YELLOW.index);
  14. HSSFCell cell = sheetRow.createCell(index++);
  15. cell.setCellStyle(colorStyle);
  16. cell.setCellValue("产品编码");
  17. cell = sheetRow.createCell(index++);
  18. cell.setCellStyle(colorStyle);
  19. cell.setCellValue("产品名称");
  20. @SuppressWarnings("unchecked")
  21. List<PmSupplierBase> dataList = (List<PmSupplierBase>)model.get("pmData");
  22. int num = null==dataList?0:dataList.size();
  23. List<CommonTypeBase> noPrList = null;
  24. if(num >= 1){
  25. noPrList = (List<CommonTypeBase>)dataList.get(0).getNoPurchaseReasonList();
  26. }
  27. String[] noPrArray = StringUtil.ListToArray(noPrList, "typeName");
  28. Map<String,String> noPrMap = (Map<String,String>)StringUtil.ListToMap(noPrList, "typeValue", "typeName");
  29. DVConstraint noPrConstraint = DVConstraint.createExplicitListConstraint(noPrArray);
  30. //四个参数分别是:起始行、终止行、起始列、终止列
  31. CellRangeAddressList noPrRegions = new CellRangeAddressList(1,num,30,30);
  32. //数据有效性对象
  33. HSSFDataValidation noPrDataValidation = new HSSFDataValidation(noPrRegions, noPrConstraint);
  34. sheet.addValidationData(noPrDataValidation);
  35. PmSupplierBase base = null;
  36. for (int i = 0; i < num; i++) {
  37. base = dataList.get(i);
  38. sheetRow = sheet.createRow(i+1);
  39. if(null==base)
  40. continue;
  41. index = 0;
  42. sheetRow.createCell(index++).setCellValue(null==base.getProductNo()?"":base.getProductNo());
  43. sheetRow.createCell(index++).setCellValue(null==base.getSupplierProductName()?"":base.getSupplierProductName());
  44. }
  45. String filename = "PSupplier" + DateUtils.dateFormatToString(currDate, "yyyyMMddHHmmss") + ".xls";//设置下载时客户端Excel的名称
  46. OutputStream ouputStream = null;
  47. try {
  48. filename = HelpUtil.encodeFilename(filename, request);//处理中文文件名
  49. response.setContentType("application/vnd.ms-excel");
  50. response.setHeader("Content-disposition", "attachment;filename=" + filename);
  51. ouputStream = response.getOutputStream();
  52. workbook.write(ouputStream);
  53. ouputStream.flush();
  54. } catch (Exception e) {
  55. e.printStackTrace();
  56. }finally{
  57. if(null!=ouputStream){
  58. ouputStream.close();
  59. }
  60. }
  61. }
  62. }

现在excel中有一列数据需要调用service类中的方法查询将结果展示,然后同事A就直接在SProductExportExcel 类中通过注解直接引入

  1. public class SProductExportExcel extends AbstractExcelView {
  2. /**同事A添加的*/
  3. @Autowired
  4. IMerwareConstantService merwareConstantService;
  5. @Override
  6. protected void buildExcelDocument(Map<String, Object> model,
  7. HSSFWorkbook workbook, HttpServletRequest request,
  8. HttpServletResponse response) throws Exception {
  9. //....
  10. //....
  11. //同事A添加的一行代码
  12. String merchantName = merwareConstantService.getMNameByMId(base.getMerchantId());
  13. }
  14. }

结果我拉取代码测试导出,后台直接报错:java.lang.NullPointException

最开始怀疑是数据的问题,在获取数据计算的时候未判断空导致的这个异常,但是debug发现是
merwareConstantService.getMNameByMId(base.getMerchantId());
这行代码merwareConstantService为空导致的。

分析代码:

如果想用@autowired,那么这个类本身也应该是在spring的管理下,即SProductExportExcel 也要标注为一个component(或Service),这样spring才知道要注入依赖。

而在controller中通过new的方式获取的SProductExportExcel,并没有交给spring管理,通过注解引入方式获取不到spring的bean对象

那么问题的关键就在于获取merwareConstantService的方式。

而获取spring的bean对象,还可以通过ApplicationContext.getBean()。

解决方案如下:

创建一个工具类,用于获取bean对象

  1. public class SpringContextUtil implements ApplicationContextAware {
  2. private static ApplicationContext applicationContext = null;
  3. @Override
  4. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  5. this.applicationContext = applicationContext;
  6. }
  7. public static ApplicationContext getApplicationContext(){
  8. return applicationContext;
  9. }
  10. /** * 适用于springbean使用注解@Service("XXXService") * 获取接口对象 参数传入 XXXService * @param beanName * @return */
  11. public static Object getBean(String beanName){
  12. return applicationContext.getBean(beanName);
  13. }
  14. /** * 适用于springbean使用注解@Service * 获取接口对象 参数传入 XXXService.class 不是 XXXServiceImpl.class * @param c * @return */
  15. public static Object getBean(Class c){
  16. return applicationContext.getBean(c);
  17. }
  18. }

然后将此bean加到spring容器中,applicationContext.xml中添加:

  1. <bean id="springContextUtil" class="com.yao.purchasing.business.impl.SpringContextUtil"></bean>

在SProductExportExcel中就通过这个工具类获取service:

  1. public class SProductExportExcel extends AbstractExcelView {
  2. /**同事A添加的*/
  3. //@Autowired
  4. //IMerwareConstantService merwareConstantService;
  5. @Override
  6. protected void buildExcelDocument(Map<String, Object> model,
  7. HSSFWorkbook workbook, HttpServletRequest request,
  8. HttpServletResponse response) throws Exception {
  9. //更改新的获取方式
  10. ApplicationContext context = SpringContextUtil.getApplicationContext();
  11. IMerwareConstantService merwareConstantService = (IMerwareConstantService)context.getBean(IMerwareConstantService.class);
  12. //....
  13. //....
  14. //同事A添加的一行代码
  15. String merchantName = merwareConstantService.getMNameByMId(base.getMerchantId());
  16. }
  17. }

再次测试导出,成功。

有一点要注意下:
IMerwareConstantService merwareConstantService = (IMerwareConstantService)context.getBean(IMerwareConstantService.class);

刚开始我传入的是类名
context.getBean(“IMerwareConstantService”);

仍然获取不到service,网上查资料发现getBean()具体传入”类名”还是 类名.class是有区别的,要根据自己的service的注解来定。

如:
@Service
public class MerwareConstantServiceImpl implements IMerwareConstantService{}
那么context.getBean()传入类名.class

@Service(“IMerwareConstantService”)
public class MerwareConstantServiceImpl implements IMerwareConstantService{}
那么context.getBean()传入类名

发表评论

表情:
评论列表 (有 0 条评论,612人围观)

还没有评论,来说两句吧...

相关阅读