如何调试spring依赖顺序?

Posted

技术标签:

【中文标题】如何调试spring依赖顺序?【英文标题】:How to debug spring dependencies order? 【发布时间】:2015-01-21 08:46:01 【问题描述】:

在这个问题的背后,我想了解和调试 Spring bean 是如何实例化的(按什么顺序)以及如何解决依赖关系。

上下文

我正在使用:

弹簧靴 弹簧安全 弹簧数据 JPA

我在 DAO 中添加了安全注释,例如:

@PreAuthorize("hasRole('ROLE_ADMIN') OR hasPermission(#entity, 'save')")
<S extends T> S save(S s);

我有一个自定义安全配置:

@Configuration
@Slf4j
public class SecurityConfiguration extends WebSecurityConfigurerAdapter 
  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth, 
                              UserDetailsService userDetailsService,
                              PasswordEncoder passwordEncoder) throws Exception 
    log.info("Configuring Authentication...");
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);

显然,自动装配的 bean 不依赖于具有安全注释的 DAO。

如果我运行 main 方法(使用 Spring Boot),无论它是编译的 jar 还是在我的 IDE 中,它都可以正常工作。但在某些情况下(例如junit测试),我得到了这个异常:

java.lang.IllegalStateException: Cannot apply org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer@362b384c to already built object

我假设 AuthenticationManagerBuilder.build() 方法已在 之前调用 Spring 创建和配置我的 SecurityConfiguration。但为什么? WebSecurityConfigurerAdapter 的顺序设置为 100,应该先完成!

问题

我如何才能看到 Spring 在配置之前创建其他 bean(DAO 和服务)的原因?如何检查我的配置服务对我的服务/dao 没有依赖关系?

谢谢,

【问题讨论】:

【参考方案1】:

@Autowired 方法将在该配置类被实例化后立即被调用(这将由 Web 容器启动时创建的安全过滤器触发)。这很早,但对于您的用例来说还不够早,因为您需要成为第一个使用 AuthenticationManagerBuilder 的人。我建议您使用 GlobalAuthenticationConfigurerAdapter(即一个新 bean),就像 Spring Boot 示例中一样(Spring Security 会更早地寻找该类型的 bean)。

【讨论】:

这行得通!但是为什么 WebSecurityConfigurerAdapter 是在 GlobalAuthenticationConfigurerAdapter 之后实例化的(有时是在一些基本服务之后)? Spring Security 控制全局身份验证与 Web 安全的顺序(我猜全局关注获胜)。早期创建的任何其他东西通常是因为其他早期事物之一需要它(例如,作为@Autowired 依赖项)。 好的。但是,如果它是一个依赖项,那么无论上下文如何(junit、depoyed、...)它都不会起作用。实际上它适用于某些情况。有没有办法让 Spring 显示它如何计算依赖树?我知道一些像 intelliJ 这样的工具可以做到这一点,但它并没有向我展示不需要的依赖。我想要真正的春天树。 您可以打开调试日志以查看正在创建的 bean。顺序可能取决于具体情况(例如,嵌入式 servlet 容器强制过滤器提前创建)。

以上是关于如何调试spring依赖顺序?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot - 依赖的初始化顺序

VS远程开发(远程调试)编译报错:对‘xxx’未定义的引用(设置库依赖顺序)(已解决)pthread(项目-->属性-->链接器-->输入-->库依赖项)

SpringBoot使用log4j2的POM依赖顺序要求

记一次循环依赖踩坑

Spring Boot 揭秘与实战 发布与部署 - 远程调试

spring循环依赖问题深究