【问题标题】:SpringBoot application does not finish starting, when using attributeconverter使用属性转换器时,Spring Boot 应用程序未完成启动
【发布时间】:2020-08-23 00:55:12
【问题描述】:

已编辑:此应用程序在添加最新的 AttributeConverter 代码之前可以正常启动和运行。我怀疑这是由于自动装配顺序。因为如果我从属性转换器中删除自动装配的 bean,则应用程序启动正常。

已编辑:cipherCreator 的代码,SecretKey

我在将值持久保存到数据库时尝试使用加密。我实现了一个属性转换器类和另一个用于初始化密码以及为密钥注入配置值的类。

当我用 AttributeConverter 装饰我的实体类进行加密时,框架没有完成启动。

它在 ===> 之后停止 触发 Spring Data 存储库的延迟初始化。 它不会抛出任何异常来停止。只是坐在那里。如果我从密码创建器中删除 Autowired 注释,它就会启动。

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.0.RELEASE)

2020-08-22 17:10:50.808  INFO 23468 --- [           main] c.c.b.data.xyzApplication   : The following profiles are active: secret,default
2020-08-22 17:10:53.811  INFO 23468 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFERRED mode.
2020-08-22 17:10:54.165  INFO 23468 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 340ms. Found 7 JPA repository interfaces.
2020-08-22 17:10:54.812  INFO 23468 --- [           main] o.s.cloud.context.scope.GenericScope     : BeanFactory id=65cd15a6-6963-3882-983e-554bc1ab6bc0
2020-08-22 17:10:55.187  INFO 23468 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'com.xyz' of type [org.springframework.cloud.openfeign.FeignClientFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-08-22 17:10:55.189  INFO 23468 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'com.xyz' of type [org.springframework.cloud.openfeign.FeignClientFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-08-22 17:10:55.190  INFO 23468 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'com.xyz' of type [org.springframework.cloud.openfeign.FeignClientFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-08-22 17:10:55.192  INFO 23468 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'com.xyz' of type [org.springframework.cloud.openfeign.FeignClientFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-08-22 17:10:55.194  INFO 23468 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'com.xyz' of type [org.springframework.cloud.openfeign.FeignClientFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-08-22 17:10:55.346  INFO 23468 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$a2393a66] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-08-22 17:10:56.480  INFO 23468 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-08-22 17:10:56.502  INFO 23468 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-08-22 17:10:56.502  INFO 23468 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.35]
2020-08-22 17:10:56.709  INFO 23468 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-08-22 17:10:56.709  INFO 23468 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 5867 ms
2020-08-22 17:10:57.755  INFO 23468 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-08-22 17:10:57.840  INFO 23468 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2020-08-22 17:11:00.487  INFO 23468 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2020-08-22 17:11:00.747  INFO 23468 --- [         task-1] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2020-08-22 17:11:00.879  INFO 23468 --- [         task-1] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.15.Final
2020-08-22 17:11:01.165  WARN 23468 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2020-08-22 17:11:01.307  INFO 23468 --- [         task-1] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2020-08-22 17:11:01.467  INFO 23468 --- [           main] DeferredRepositoryInitializationListener : Triggering deferred initialization of Spring Data repositories�
2020-08-22 17:11:01.951  INFO 23468 --- [         task-1] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect
2020-08-22 17:11:02.470  WARN 23468 --- [         task-1] org.hibernate.cfg.AnnotationBinder       : 

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Base64;

@Component
@Converter
public class CustomerEncryptor implements AttributeConverter<String, String>{

    @Autowired
    CipherCreator cipherCreator;

    @Override
    public String convertToDatabaseColumn(String attribute) {
        if(StringUtils.isEmpty(attribute))
            return attribute;
        try {
            return do something...
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String convertToEntityAttribute(String dbData) {
        if(StringUtils.isEmpty(dbData))
            return dbData;
        try {
            do something...
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

我注意到如果我不使用

    [@]Autowired
    CipherCreator cipherCreator;

应用程序启动。

感谢任何想法

import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;

@Setter
@Getter
@Component
public class CipherCreator {
    private static String ALGORITHM = "AES";
    private Key key;
    private Cipher cipherEnc;
    private Cipher cipherDec;

    @Autowired
    public CipherCreator(SecretKeyProperty keyProperty) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
        key = new SecretKeySpec(keyProperty.getSECRETKEY().getBytes(), ALGORITHM);

        cipherEnc = Cipher.getInstance(ALGORITHM);
        cipherEnc.init(Cipher.ENCRYPT_MODE, key);
        cipherDec = Cipher.getInstance(ALGORITHM);
        cipherDec.init(Cipher.DECRYPT_MODE, key);
    }
}
@Component
public class SecretKeyProperty {

    public String SECRETKEY;


    @Autowired
    public SecretKeyProperty(@Value("${encryption.key}") final String key)  {
        this.SECRETKEY = key;
    }

    public String getSECRETKEY() {
        return SECRETKEY;
    }

    public void setSECRETKEY(String sECRETKEY) {
        SECRETKEY = sECRETKEY;
    }

}

【问题讨论】:

  • 你在某处有循环依赖吗?创建CipherCreator 的代码在哪里?我还要说您的实现有缺陷,您在转换时返回 null 并发生异常,这样您可能会丢失数据(我怀疑您应该抛出异常)。尝试将spring.data.jpa.repositoriesbootstrap-mode=DEFAULT 添加到您的配置中,这可能会触发其他代码的一些早期初始化。
  • 是的,但我尝试创建一个没有循环依赖的新的非常简单的实体并对其进行装饰,结果相同
  • 我也尝试删除所有循环依赖项进行测试,但它仍然无法启动。
  • 这与实体无关,而与您的转换器有关。您可能希望使用调试日志记录运行以查看发生了什么以及它停止的确切位置。我还建议升级到 Spring Boot 2.3.3(因为您已经在 2.3 范围内)。
  • @iamomie 我最近遇到了完全相同的问题,从春天的2.3.x2.2.9 为我解决了这个问题

标签: java spring spring-boot encryption dependency-injection


【解决方案1】:

这是由于更改了boostrap mode in JPA 造成的。引用更改:

将一般默认值更改为 deferred - 它并行化 EntityManagerFactory 的引导程序并将存储库初始化延迟到 ApplicationContext 初始化结束

要解决您的问题,请使用默认引导模式 (spring.data.jpa.repositories.bootstrap-mode=default)。

(向 VMware 的 Stéphane Nicoll 提供帮助,请参阅 this discussion at spring github

【讨论】:

    【解决方案2】:

    尝试将@Component 注释添加到您的AttributeConverter,但不是@Converter 注释。

    我猜这个问题是由于 Spring 创建它的 bean 和 JPA 创建它的 bean 之间的某种互锁,并且两者都知道另一个,这要感谢两个社区的努力使 AttributeConverter compatible with Spring beans。 在我的项目中,仅使用 @Component 就可以了:我想 Spring 然后创建 所有 bean,包括 AttributeConverter bean,后来被 JPA 借用......而不是 Spring JPA 竞争创建 bean,使用彼此的依赖关系,这可能会导致互锁。

    【讨论】:

      【解决方案3】:

      Spring Boot 嵌入式 tomcat 以 spring-boot-starter 或 spring-boot-starter-web(flux) 启动。确保你在 pom 中有这些依赖项

      【讨论】:

      • 如果我从要转换的实体中删除 attributeConverter 注释,此应用程序将正常启动。
      • 这无济于事,也不是解决方案。如果您阅读了这个问题,它确实可以在没有转换器的情况下正常启动,并且在启动过程中转换器会挂起。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-22
      • 1970-01-01
      相关资源
      最近更新 更多