当 @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 分钟才能启动调用方法的主要内容,如果未能解决你的问题,请参考以下文章
@Bean在@Configuration和在@Component中的区别
@Controller,@Service,@Repository,@Component你搞懂了吗?