如何根据变量延迟Spring Bean初始化

Edw*_*rew 4 java lazy-loading spring-boot

我的问题是,在调用 API 之前我需要获取身份验证令牌。必须在应用程序启动时调用 api。然而,我遇到了麻烦,因为两个调用是同时进行的,因此在进行 api 调用之前产生了没有身份验证令牌的错误。

我基本上需要 tokenUtilityClass 在实例化 Paypal 类之前创建令牌。我已经尝试过 @Preconstruct 和 @Lazy 注释,但两者都不适合我。

我有一个 validToken 的布尔值,一旦创建身份验证令牌,该值将返回 true。

这就是我的 Springboot 配置文件的样子

@Autowired
private TokenUtilityClass tokenUtilityClass;


  @Bean ResourceConfig resourceConfig() {
      return new ResourceConfig().registerClasses(Version1Api.class); }

  @PostConstruct
  public void postConstruct() {
      tokenUtilityClass.tokenTimer();
  }


@DependsOn("TokenUtilityClass")
@ConditionalOnProperty(name ="tokenUtilityClass.validToken", havingValue ="true")
@Lazy
public Paypal eventPublisherBean() {
    return new Paypal();
}
Run Code Online (Sandbox Code Playgroud)

有人会对仅在生成身份验证令牌后初始化 Paypal 类有任何想法吗?

所有帮助将不胜感激

dav*_*xxx 5

您声明的内容不起作用:

@DependsOn("TokenUtilityClass")
@ConditionalOnProperty(name ="tokenUtilityClass.validToken", havingValue ="true")
@Lazy
Run Code Online (Sandbox Code Playgroud)

因为tokenUtilityClass.validToken它不是一个属性,而是一个 bean 方法,而 ConditionalOnProperty需要一个属性。

有人会对仅在生成身份验证令牌后初始化 Paypal 类有任何想法吗?

具体来说,您无法直接使用 Spring 来实现它,因为一旦依赖项中的其他 bean 需要这些 bean,就会立即实例化这些 bean。

但仅声明:

@Bean
@Lazy
public Paypal eventPublisherBean() {
    return new Paypal();
}
Run Code Online (Sandbox Code Playgroud)

如果该 bean 从未用作其他 bean 的急切加载依赖项,而是在您合适的时候需要:在检索令牌之后,则可以工作。
要实现这一目标,您有两种方法:

1)不要使用依赖注入PayPal,而只使用bean工厂。
未经测试,但听起来符合@Lazyjavadoc :

如果 @Component 或 @Bean 定义中不存在此注释,则会发生急切初始化。如果存在并设置为 true,@Bean 或 @Component 将不会被初始化,直到被另一个 bean 引用或从封闭的 BeanFactory 显式检索。

因此,注入BeanFactory负责获取令牌的 bean 并在检索令牌后使用该工厂初始化 bean。
像这样的东西:

@Service
public class TokenUtility {

   private BeanFactory factory;

   public TokenUtility(BeanFactory factory){
     this.factory = factory;
   }

   public Token retrieveToken(){
     // call service to get the token
     //...
     // init the bean now -(it will also invoke its @PostConstruct method)
     PayPal payPal = beanFactory.getBean(PayPal.class);
   }

}
Run Code Online (Sandbox Code Playgroud)

2) BeanFactory 的更直接替代方案是将 bean 声明为惰性依赖项:

@Service
public class TokenUtility {

  @Lazy
  @Autowired
  Paypal paypal;

  public Token retrieveToken(){
         // call service to get the token
         //...
         // init the bean by invoking any method on that
          paypal.init();
       }
}
Run Code Online (Sandbox Code Playgroud)

我刚刚创建了一个非常基本的项目(Java 11)来测试: https: //github.com/ebundy/lazy-init-spring-example/

当你执行时spring-boot:run你应该得到:

2020-02-26 09:38:05.883 INFO 7002 --- [ main] osweb.context.ContextLoader :根 WebApplicationContext:初始化在 682 毫秒内完成
TokenUtility init 状态代码=200
贝宝初始化