@Autowired从Spring Boot中注入的service在WAR中为null。

huangapple go评论73阅读模式
英文:

@Autowired service from Spring Boot is null in WAR

问题

首先,我为给您带来不便道歉,我提供这个咨询是因为我已经花了好几天时间来解决这个问题,但是我找不到正确的解决方案。我有一个名为"fact-electronica-api"的项目,使用Swagger Codegen进行设计,通过它我可以得到执行REST调用的路径。一旦用户进行了这种调用,API项目会与另一个使用Spring Boot的核心项目进行通信,后者会与数据库执行查询。我的问题是,当我在API中对核心中定义的服务进行自动装配(Autowired)时,该服务始终为null。

请原谅我的英语,我来自乌拉圭,我希望您能理解我所面临的问题。为了更好地理解,我已经附上了一些图片。

  • Fact electronica Api

@Autowired从Spring Boot中注入的service在WAR中为null。

  • Factelec-core

@Autowired从Spring Boot中注入的service在WAR中为null。

通过该服务接收REST调用,并与核心进行通信。

@Autowired从Spring Boot中注入的service在WAR中为null。

核心中的服务

@Autowired从Spring Boot中注入的service在WAR中为null。

API对核心的依赖关系

@Autowired从Spring Boot中注入的service在WAR中为null。

Spring Boot初始化器,在您启动Wildfly中的EAR文件时,该项目会自动启动并进行相关设置。

@Autowired从Spring Boot中注入的service在WAR中为null。

如果有人能够指导我解决这个问题,我将不胜感激,提前感谢您。

英文:

first of all I apologize for the inconvenience, I make this consultation because I have spent days with this problem and I do not find the right solution. I have a project called fact-electronica-api designed using swagger codegen, through this I have the paths to perform REST calles. Once the user makes a call of this type the api project communicates with another project that has the core which use Spring Boot and performs the query with the database. The problem I have is that when I make from the api an autowired to the service defined in the core this is null.

Excuse my English, I am from Uruguay, I hope you understand the problem I am facing.For further understanding, I have attached images.

  • Fact electronica Api

@Autowired从Spring Boot中注入的service在WAR中为null。

  • Factelec-core

@Autowired从Spring Boot中注入的service在WAR中为null。

Service through which I receive the rest call and communicate with the core.

@Autowired从Spring Boot中注入的service在WAR中为null。

Service in core

@Autowired从Spring Boot中注入的service在WAR中为null。

Dependence on the api to the core

@Autowired从Spring Boot中注入的service在WAR中为null。

Spring Boot initializer, when you start the ear in wildfly, this project starts automatically and makes the relevant settings.

@Autowired从Spring Boot中注入的service在WAR中为null。

I would be grateful if someone could guide me in solving this problem, thank you in advance.

答案1

得分: 2

似乎 SolicitudApiServicelmpl 不是一个 Spring bean,因此 Spring 不会考虑对所有使用 @Autowired 注解的类字段进行依赖注入。尝试将该类标注为 @Service,将类的实例添加到 Spring 上下文中,或者为 SolicitudApiServicelmpl 创建一个工厂,在其中生成 Spring 代理而不是一个简单的对象。

英文:

Seems like SolicitudApiServicelmpl isn't a Spring bean, so Spring wouldn't consider all class's fields annotated with @Auowired for dependency injection. Try to annotate this class as @Service to add the class's instance to Spring context or create a factory for
SolicitudApiServicelmpl which generates Spring proxy instead of a simple object.

答案2

得分: 1

你没有在创建 SolicitudApiServicelmpl 的 Spring 实例。

Spring 上下文(使 @Autowired 起作用)需要你通过 Spring 创建该实例,而不是使用 Java 的 new SolicitudApiServicelmpl()

你可以使用多种技术来创建该实例,以下是其中一些方法:

使用静态上下文和“手动装配”(不推荐)

public class Main {

   private static ConfigurableApplicationContext context;

   public static void main(String[] args) {
      context = SpringApplication.run(MyApplication.class, args);
   }

   public static ConfigurableApplicationContext getContext() {
      return context;
   }

}
public class SolicitudApiServicelmpl {

   private ConfigurableApplicationContext context = Main.getContext();

   private SolicitudInformacionService solInfServ = context.getBean(SolicitudInformacionService.class);

   // 现在 `solInfServ` 不再为空。
   // ...
}

在 Spring 上下文中创建 SolicitudApiServicelmpl 实例

@Component
public class SomeClassWithSpringContext {

   @Autowired private SolicitudApiServicelmpl solicitudService;
   // 这样,@Autowired 应该在 `solicitudService` 实例中起作用。

}

或者使用上下文实例:

@Component
public class SomeClassWithSpringContext {

   @Autowired private WebApplicationContext context;

   public void someMethodOrSomewhere() {
      SolicitudApiServicelmpl service = context.getBean(SolicitudApiServicelmpl.class);
      // 这样,@Autowired 应该在 `service` 实例中起作用。
   }

}
英文:

You are not creating SolicitudApiServicelmpl spring instance.

Spring context (witch makes @Autowired work) needs you to create that instance thought to Spring and not with a java native new SolicitudApiServicelmpl().

You can create that instance with a lot of techniques, here you have some of them:

Static context with "manual wired" (not recommended)

public class Main {

   private static ConfigurableApplicationContext context;

   public static void main(String[] args) {
      context = SpringApplication.run(MyApplication.class, args);
   }

   public static ConfigurableApplicationContext getContext() {
      return context;
   }

}
public class SolicitudApiServicelmpl {

   private ConfigurableApplicationContext context = Main.getContext();

   private SolicitudInformacionService solInfServ = context.getBean(SolicitudInformacionService.class);

   // Now `solInfServ` is not null anymore.
   // ...
}

Creating a SolicitudApiServicelmpl instance within the Spring context

@Component
public class SomeClassWithSpringContext {

   @Autowired private SolicitudApiServicelmpl solicitudService;
   // with this @Autowired should work in the `service` instance.

}

or with the context instance:

@Component
public class SomeClassWithSpringContext {

   @Autowired private WebApplicationContext context;

   public void someMethodOrSomewhere() {
      SolicitudApiServicelmpl service = context.getBean(SolicitudApiServicelmpl.class);
      // with this @Autowired should work in the `service` instance.
   }

}

答案3

得分: 0

经过 Nurio Fernández 和 Andrei Kovrov 给予我的帮助,我能够找到实现我想要做的事情的正确方法。

首先,我将 Spring 集成到了 API 中,而不仅仅是核心部分,将 Spring Boot 从核心部分移动到了 API 中,结果在 API 中出现了以下类。

Api - ApplicationInitializer.java

@Order(Ordered.HIGHEST_PRECEDENCE)
@SpringBootApplication(scanBasePackages = {"com.factelcore.*","uy.com.antel.fact.*"})
@EnableJpaRepositories("com.factelcore.repository")
public class ApplicationInitializer extends SpringBootServletInitializer {
    
    public static void main(String[] args){
        SpringApplication.run(ApplicationInitializer.class,args);
    }
    
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(applicationClass);
    }
 
    private static Class<ApplicationInitializer> applicationClass = ApplicationInitializer.class;
    
}

通过这样做,我确保在 API 中有了一个 Spring 上下文,我可以在其中进行操作。当我从这里启动 Spring 时,我扫描了所有的 API 和核心文件,并对 Bean 进行了适当的配置。

在这样做之后,我需要捕获上下文以恢复在核心中定义的 Bean,这样我就可以使用核心中定义的 @Service 类。为此,我创建了以下类:

Api - AppContextUtil.java

@Component
public class AppContextUtil implements ApplicationContextAware {
    
    @Autowired 
    private WebApplicationContext context;

    private static ApplicationContext appContext;
    
    @PostConstruct
    public void init() {
        if (context != null) {
            setApplicationContext(context);    		
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        AppContextUtil.appContext = applicationContext;
    }

    public static ApplicationContext getContext() {
        return appContext;
    }
}

完成这一步后,使用 SolicitudApiServiceImpl,我可以通过以下方式在特定时刻调用所需的 Bean:

Api - SolicitudApiServiceImpl.java

ApplicationContext cont = AppContextUtil.getContext();
SolicitudInformacionService solInfServ = cont.getBean(SolicitudInformacionService.class);

我不知道这是否是理想的方法,但在我的情况下对我起作用,如果有人知道更好的方法,请随意告诉我,以便我可以改进代码。非常感谢!

英文:

after the help that was given to me by Nurio Fernández and Andrei Kovrov i was able to find out the right way to accomplish what i wanted to do.

First of all I integrate Spring into the api, and not only into the core, moving spring boot from the core to the api, resulting in this class in the api.

> Api - ApplicationInitializer.java

@Order(Ordered.HIGHEST_PRECEDENCE)
@SpringBootApplication(scanBasePackages = {&quot;com.factelcore.*&quot;,&quot;uy.com.antel.fact.*&quot;})
@EnableJpaRepositories(&quot;com.factelcore.repository&quot;)
public class ApplicationInitializer extends SpringBootServletInitializer {
	
	public static void main(String[] args){
		SpringApplication.run(ApplicationInitializer.class,args);
    }
    
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(applicationClass);
    }
 
    private static Class&lt;ApplicationInitializer&gt; applicationClass = ApplicationInitializer.class;
    
}

By doing this I made sure I had a spring context in the api, which I could work with. When I start Spring from here I scan all the api and core files, performing the appropriate configuration of the beans.

After doing this, I needed to capture the context to recover the beans that are defined in the core, so I could work with the @Service class defined in the core. For this I created the following class:

> Api - AppContextUtil.java

@Component
public class AppContextUtil implements ApplicationContextAware {
	
	@Autowired 
    private WebApplicationContext context;

    private static ApplicationContext appContext;
    
    @PostConstruct
    public void init() {
    	if (context != null) {
    		setApplicationContext(context);    		
    	}
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    	AppContextUtil.appContext = applicationContext;
    }

    public static ApplicationContext getContext() {
        return appContext;
    }
}

Once this was done, using the SolicitudApiServiceImpl I was able to do the following to invoke the bean I needed at a certain time:

Api - SolicitudApiServiceImpl.java

ApplicationContext cont = AppContextUtil.getContext();
SolicitudInformacionService solInfServ = cont.getBean(SolicitudInformacionService.class);

I don't know if this is the ideal way to do this, but in my case it worked for me, if there is someone who has a better way to do it feel free to tell me so I can improve the code. Thank you very much!

huangapple
  • 本文由 发表于 2020年10月17日 03:27:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/64395245.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定