如何调试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依赖顺序?的主要内容,如果未能解决你的问题,请参考以下文章
VS远程开发(远程调试)编译报错:对‘xxx’未定义的引用(设置库依赖顺序)(已解决)pthread(项目-->属性-->链接器-->输入-->库依赖项)