当 @Repository 注释 bean 的代理时,JdkDynamicAopProxy 需要超过 1 分钟才能启动调用方法

Posted

技术标签:

【中文标题】当 @Repository 注释 bean 的代理时,JdkDynamicAopProxy 需要超过 1 分钟才能启动调用方法【英文标题】:JdkDynamicAopProxy takes over 1 minute to start invoke method when proxy of a @Repository annotated bean 【发布时间】:2020-02-27 05:27:29 【问题描述】:

问题

在我的构造函数注入的存储库 bean 上调用 save 方法时遇到了一个非常奇怪的问题。我已将问题缩小到 JdkDynamicAopProxy,它是 intelliJ 框架概述中可见的第一个调用方法。我在调用方法的第一行放了一个断点。从调用到断点需要一分钟多的时间。在这两个帧之间没有(明显地)发生任何事情。

代码

控制器

    @Controller
    class LoginController(private val userRepository: UserRepository, val passwordEncoder: PasswordEncoder) 

        @PostMapping(value = ["/register"])
        fun register(@RequestParam("mail") mail: String?, @RequestParam("password") pass: String?, model: Model) : ModelAndView
        
            val modelAndView = ModelAndView("index")
            if (mail == null || mail == "" || pass == null || pass == "") 
                modelAndView.status = HttpStatus.NOT_ACCEPTABLE;
                return modelAndView
            
            // IT IS THE NEXT LINE WHICH IS CAUSING THE LONG WAIT...
            userRepository.save(User(email = mail, password = passwordEncoder.encode(pass), newPassword = pass, firstname = "Test", lastname = "Persoon"))
            modelAndView.status = HttpStatus.OK
            return modelAndView

        
    

用户存储库

    @Repository
    interface UserRepository : JpaRepository<User, Long> 
        fun findByEmail(email: String): User
    

application.properties

    spring.datasource.url=jdbc:mysql://localhost:3306/db?serverTimezone=GMT%2B1&useSSL=FALSE&allowPublicKeyRetrieval=true
    spring.datasource.username=username
    spring.datasource.password=password
    spring.datasource.hikari.connectionTimeout=20000
    spring.datasource.hikari.maximumPoolSize=5
    spring.datasource.hikari.poolName=Connections

    spring.jpa.hibernate.ddl-auto=update
    spring.jpa.show-sql=true
    spring.jpa.database=mysql
    spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect

    spring.thymeleaf.suffix=.xhtml

    logging.level.org.springframework=INFO
    logging.level.com.zaxxer=ERROR
    logging.level.com.jenson=INFO
    logging.level.root=ERROR
    logging.level.org.hibernate.type=TRACE

框架

来自寄存器:33,loginController 调用:157,JdkDynamicAopProxy 需要超过 1 分钟。

我似乎无法在两者之间输入那个“框架”..

Overview of the last frames during execution

编辑:最终的解决方案

不是调用,而是密码编码问题。

问题出在 BCryptEncoder bean 中。

    fun bCryptEncoder() : PasswordEncoder = BCryptPasswordEncoder(20)

检查 BCryptEncoder 的源代码告诉我 10 是空构造函数强度。现在使用空的构造函数和方法只需要不到一秒钟的时间。

【问题讨论】:

【参考方案1】:

我在那条“慢行”上看到passwordEncoder.encode(pass)。这就是为什么我认为这可能是经典的“/dev/urandom”问题。

https://ruleoftech.com/2016/avoiding-jvm-delays-caused-by-random-number-generation

如果您从 IDE 运行此代码,请确保实际的 JVM(运行您的程序,而不是您的 IDE)具有此配置。

【讨论】:

你是英雄!我首先将 pw 的编码提取到一个变量中。缓慢的执行发生在那里,而不是在存储库的调用中...... 很高兴能帮上忙 :) 最终不是随机数生成策略,但您的评论为我指出了正确的解决方案。 (见编辑)改变随机生成“策略”并没有什么不同。

以上是关于当 @Repository 注释 bean 的代理时,JdkDynamicAopProxy 需要超过 1 分钟才能启动调用方法的主要内容,如果未能解决你的问题,请参考以下文章

如何将属性值注入使用注释配置的 Spring Bean?

Spring Boot 似乎没有找到 Repository

@Bean在@Configuration和在@Component中的区别

@Controller,@Service,@Repository,@Component你搞懂了吗?

当 bean 具有带有 @Formula 注释的属性时,findRowCount 不起作用

@Component 和 @Bean 的区别