springboot中定义的普通类,注入到其他service中使用,为啥报如下错误?

作者站长头像
站长
· 阅读数 9

注入

@Service
public class FgStoServiceImpl implements FgStoService {
   
    @Resource
    private PrintInvoiceService printInvoiceService;
     public TransResult printVNPT(OdsProStoHvDetail condition) {
       
            PublishServiceSoap publishServiceSoap = printInvoiceService.getPublishServiceSoap();
...
}

定义的普通类(这种普通类有20多个,是不是只能是都加上component注解?)

package com.haier.cosmo.wms.cp.out.service.service.printInvoiceService;

import java.net.MalformedURLException;
import java.net.URL;

public class PrintInvoiceService {
    private PublishServiceSoap publishServiceSoap;

    public PublishServiceSoap getPublishServiceSoap() {
        String url = "https://aquavn-tt78admindemo.vnpt-invoice.com.vn/PublishService.asmx";
        if (publishServiceSoap != null) {
            return publishServiceSoap;
        }
        try {
            URL uurl = new URL(url);//URL在配置文件中动态配置
            PublishService mobileCodeWS = new PublishService(uurl);
            publishServiceSoap = mobileCodeWS.getPublishServiceSoap();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return publishServiceSoap;
    }
}

报错


Description:

A component required a bean of type 'com.haier.cosmo.wms.cp.out.service.service.printInvoiceService.PrintInvoiceService' that could not be found.


Action:

Consider defining a bean of type 'com.haier.cosmo.wms.cp.out.service.service.printInvoiceService.PrintInvoiceService' in your configuration.
回复
1个回答
avatar
test
2024-07-04

不一定但一般是这样的。如果你需要让Spring来管理你定义的类,你就需要首先把这些bean放进Spring的容器里交给Spring来管理,诸如@Component/@Controller/@Service/@Repository其实本质上都是一样的,就是把这个类的对象或者实现这个接口的类的对象交给Spring容器来管理。一个可能不太恰当的比喻:你可以理解为没加注解的类是水龙头里的水,每次你要用水都得自己打开水龙头,加上这些注解的类是被装进水瓶里的水,你要用的时候只要从水瓶里倒水就可以了,前提是你得往这个水瓶里装水。另外我注意到你的这个普通类里面:

PublishService mobileCodeWS = new PublishService(uurl);

如果你要给这个普通类加上@Component注解,这里的写法也就相应地要变化,PublishService也要加上@Component/@Service,再通过@Resource/@Autowired注入这个已经加上@Component的普通类里(现在已经是交给Spring管理的类了),如果你的类里还有这种new的对象,就要一路改下去直到没有这种情况为止。当然了,你如果非要在一个已经交给Spring管理的类里new对象,然后还要通过Spring容器拿到这个bean,就不能采用注入的方式了,不然会报空指针异常,这里我提供一个工具类:

 
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

@Component
public class SpringUtils implements ApplicationContextAware {
    
    private static ApplicationContext applicationContext;
    
    /**
     * 服务器启动,Spring容器初始化时,当加载了当前类为bean组件后,
     * 将会调用下面方法注入ApplicationContext实例
     */
    @Override
    public void setApplicationContext(ApplicationContext arg0) throws BeansException {
        System.out.println("Spring容器初始化了");
        SpringUtils.applicationContext = arg0;
    }
    
    public static ApplicationContext getApplicationContext(){
        return applicationContext;
    }
    
    /**
         * 外部调用这个getBean方法就可以手动获取到bean
     * 用bean组件的name来获取bean
     * @param beanName
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T>T getBean(String beanName){
        return (T) applicationContext.getBean(beanName);
    }
}

调用它的getBean方法就能拿到你那个里面有new对象的bean了:

//我假设你非要保留PrintInvoiceService里的PublishService mobileCodeWS = new PublishService(uurl)不可
PrintInvoiceService printInvoiceService = springUtils.getBean("printInvoiceService");

其实本质上就是直接拿到容器对象,然后调用容器的getBean方法“手动”来拿到我们想要的bean罢了,这种方式适用于在一些不能被Spring管理的类里非得用到Spring管理的类的对象时。希望我的回答对你有所帮助。

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容