@Autowired注解在application.java中的Service类实例为空。

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

@Autowired instance of Service class is null in the application.java

问题

@Service
public class TokenServiceImpl implements TokenService{

private final Settings settings;

private final RestTemplate restTemplate;

@Autowired
public TokenServiceImpl(Settings settings, @Qualifier("rstProxy") RestTemplate restTemplate) {
    this.settings= settings;
    this.restTemplate = restTemplate;
}
//...

}

Application.java

@SpringBootApplication
@EnableAsync
@EnableScheduling
public class Application extends SpringBootServletInitializer {

@Autowired
private TokenService tokenService; // 返回 null

//.......

@Bean("rstProxy")
public RestTemplate restTemplateWithProxy() {
    final List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
    messageConverters.add(new ByteArrayHttpMessageConverter());
    messageConverters.add(new StringHttpMessageConverter());
    messageConverters.add(new ResourceHttpMessageConverter());
    messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
    messageConverters.add(new MappingJackson2HttpMessageConverter());

    final RestTemplate restTemplate = new RestTemplate();

    List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
    interceptors.add(new AuthorizationInterceptor(tokenService));
    restTemplate.setInterceptors(interceptors);
    restTemplate.getMessageConverters().addAll(messageConverters);

    restTemplate.setRequestFactory(factory);
    return restTemplate;
}

}

为什么 TokenService 返回 null?但如果我从构造函数中移除 @Qualifier("rstProxy"),它就能工作。你有解决方案吗?我需要这个 @qualifier。

英文:

I am a little confused,why @Autowired instance of the Service class is null

@Service
        public class TokenServiceImpl implements TokenService{
        
        	private final Settings settings;
        
            private final RestTemplate restTemplate;
        
            @Autowired
            public TokenServiceImpl(Settings settings, @Qualifier(&quot;rstProxy&quot;) RestTemplate restTemplate) {
                this.settings= settings;
                this.restTemplate = restTemplate;
            }
        	//...
        	
        }

Application.java

        @SpringBootApplication
        @EnableAsync
        @EnableScheduling
        public class Application extends SpringBootServletInitializer {
        
        	@Autowired
        	private TokenService tokenService; // return null
        
            //.......

@Bean(&quot;rstProxy&quot;)
	public RestTemplate restTemplateWithProxy() {
		final List&lt;HttpMessageConverter&lt;?&gt;&gt; messageConverters = new ArrayList&lt;&gt;();
		messageConverters.add(new ByteArrayHttpMessageConverter());
		messageConverters.add(new StringHttpMessageConverter());
		messageConverters.add(new ResourceHttpMessageConverter());
		messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
		messageConverters.add(new MappingJackson2HttpMessageConverter());

		final RestTemplate restTemplate = new RestTemplate();

		List&lt;ClientHttpRequestInterceptor&gt; interceptors = new ArrayList&lt;&gt;();
		interceptors.add(new AuthorizationInterceptor(tokenService));
		restTemplate.setInterceptors(interceptors);
		restTemplate.getMessageConverters().addAll(messageConverters);

		restTemplate.setRequestFactory(factory);
		return restTemplate;
	}
        }

Why the TokenService returns null ?
But If I remove the @Qualifier(&quot;rstProxy&quot;) from my constructor, it works. Do you have a solution ? I need this @qualifier

答案1

得分: 1

第一点:Spring Bean 的实例化顺序没有保证,除非您明确指定。

@Autowired
@Lazy // 这将在请求时加载 Bean
private TokenService tokenService;

如果上述方法不起作用,可以继续尝试重构您的 TokenServiceImpl,使其在构造函数之后接受 setter 方法:

private RestTemplate restTemplate; 

public TokenServiceImpl(Settings settings) {
    this.settings= settings;
}

@Autowired
public void setRestTemplate(@Qualifier("rstProxy") RestTemplate restTemplate) {
    this.restTemplate = restTemplate;
}

现在,TokenService 将在不等待 RestTemplate 的情况下创建。然后,当 RestTemplate 被创建时,它可以通过我们创建的 setter 方法注入到 TokenService 中。

英文:

First: Spring beans are instantiated in no guaranteed order, unless you specify it

@Autowired
@Lazy //this will load Bean when it is requested
private TokenService tokenService;

If above not work then continue and try to refactor your TokenServiceImpl to accept setter method after constructor:

    private RestTemplate restTemplate; 

    public TokenServiceImpl(Settings settings) {
        this.settings= settings;
    }

    @Autowired
    public void setRestTemplate(@Qualifier(&quot;rstProxy&quot;) RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

Now TokenService is created without waiting for the RestTemplate.
Then, when the RestTemplate is created, It can inject it into the TokenService via setter method that we created.

答案2

得分: 0

@SpringBootApplication 本身不是 @Component,不会注入任何依赖到你的 Application 类(它实际上不是一个 Bean)。你需要明确告诉 Spring,Application 类本身也是一个 Bean:

@Service // <--- 在应用程序上下文中注册为服务
@SpringBootApplication
@EnableAsync
@EnableScheduling
public class Application extends SpringBootServletInitializer {

    @Autowired
    private TokenService tokenService;

    public static void main(final String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

但我建议你只将你的应用程序作为启动 Spring 应用程序的入口点,而不要直接参与其中。

英文:

@SpringBootApplication itself is not a @Component and no dependencies will be injected into your Application class (it's simply not a bean). You need to explicitly tell Spring that the Application class itself is a bean too:

@Service // &lt;-- register as service in application context
@SpringBootApplication
@EnableAsync
@EnableScheduling
public class Application extends SpringBootServletInitializer {

    @Autowired
    private TokenService tokenService;

    public static void main(final String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

But I'd recommend using your application only as entry point to start the Spring application, but not take part in it itself.

答案3

得分: 0

另一个答案,第二个:

当您在TokenServiceImpl的构造函数中将@Lazy注解添加到RestTemplate bean时,它告诉容器只有在第一次调用时才创建该bean,而不是在应用程序启动时。

  @Autowired
  public TokenServiceImpl(Settings settings, @Lazy @Qualifier("rstProxy") RestTemplate restTemplate) {
    this.settings= settings;
    this.restTemplate = restTemplate;
  }

这可能会使您的tokenServiceImpl bean不为空。

英文:

Another answer, second one:
When you add @Lazy annotation to the RestTemplate bean in the constructor of TokenServiceImpl, it tells to Container to create this bean only when it is first time called, not at the application startup.

  @Autowired
  public TokenServiceImpl(Settings settings, @Lazy @Qualifier(&quot;rstProxy&quot;) RestTemplate restTemplate) {
    this.settings= settings;
    this.restTemplate = restTemplate;
  }

This above probably make your tokenServiceImpl bean to not be a null.

huangapple
  • 本文由 发表于 2023年7月20日 16:55:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76728214.html
匿名

发表评论

匿名网友

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

确定