【问题标题】:Autowired property is null - Spring Boot ConfigurationAutowired 属性为空 - Spring Boot 配置
【发布时间】:2014-01-18 08:36:55
【问题描述】:

我在自动装配的属性中遇到了空值。我希望我能得到一些帮助。

我们正在为项目使用 spring-boot 版本 0.5.0.M6。

四个带bean的配置文件在一个包中,按“面积”排序:

  1. 数据源配置
  2. 全局方法安全配置(我们使用 Spring-ACL)
  3. MVC 配置
  4. Spring 安全配置

引导一切的主要方法在以下文件中:

@EnableAspectJAutoProxy
@EnableSpringConfigured
@EnableAutoConfiguration(exclude = {
    DataSourceTransactionManagerAutoConfiguration.class,
    HibernateJpaAutoConfiguration.class,
    JpaRepositoriesAutoConfiguration.class,
    SecurityAutoConfiguration.class,
    ThymeleafAutoConfiguration.class,
    ErrorMvcAutoConfiguration.class,
    MessageSourceAutoConfiguration.class,
    WebSocketAutoConfiguration.class
})
@Configuration
@ComponentScan
public class IntegrationsImcApplication {

    public static void main(String[] args) throws Exception {
        ApplicationContext ctx = SpringApplication.run(
                IntegrationsImcApplication.c lass, args);
    }
}

保存数据源配置bean的第一个文件如下(我省略了一些方法主体部分以使其更具可读性):

@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
@Configuration
public class RootDataSourceConfig 
        extends TomcatDataSourceConfiguration 
        implements TransactionManagementConfigurer {

    @Override
    public DataSource dataSource() {
        return jpaDataSource();
    }

    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return jpaTransactionManager();
    }

    @Bean
    public HibernateExceptionTranslator hibernateExceptionTranslator() {
        return new HibernateExceptionTranslator();
    }

    @Bean(name="jpaDataSource")
    public DataSource jpaDataSource() {......}

    @Bean(name = {"transactionManager","txMgr"})
    public JpaTransactionManager jpaTransactionManager() {......}

    @Bean(name = "entityManagerFactory")
    public EntityManagerFactory jpaEmf() {......}
}

这是下一个配置文件,它取决于上面的数据源。它有大约 20 个与 ACL 配置相关的 bean,但它在第一个使用数据源的 bean 上失败:

@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public class RootGlobalMethodSecurityConfig 
        extends GlobalMethodSecurityConfiguration 
        implements Ordered {

    @Autowired
    public DataSource dataSource;

    @Override
    public int getOrder() {
        return IntegrationsImcApplication.ROOT_METHOD_SECURITY_CO NFIG_ORDER;
    }

    @Bean
    public MutableAclService aclService() 
            throws CacheException, IOException {

        MutableJdbcAclService aclService = new MutableJdbcAclService(
                dataSource, aclLookupStrategy(), aclCache());
        aclService.setClassIdentityQuery("SELECT @@IDENTITY");
        aclService.setSidIdentityQuery("SELECT @@IDENTITY");
        return aclService;
    }

    ...................................
}

基本上调用aclService() 会引发错误,因为dataSource 为空。我们已经尝试通过实现Ordered 接口来订购配置文件。我们也尝试使用@AutoConfigureAfter(RootDataSourceConfig.class),但这也无济于事。除了在DataSource 上执行@Autowired 之外,我们还尝试注入RootDataSourceConfig 类本身,但它仍然为空。我们尝试在这些 bean 上使用 @DependsOn@Ordered,但同样没有成功。似乎无法将任何内容注入此配置。

启动时的控制台输出会按照我们想要的顺序列出 bean,其中数据源是第一个。我们几乎被这个阻止了。

我们在这里做的任何奇怪或独特的事情都不起作用吗?如果这是设计的,那我们怎么能以不同的方式注入数据源呢?

回购:github

【问题讨论】:

  • 可能有一些我们没有看到的代码会强制提前实例化您的RootGlobalMethodSecurityConfig。您能否分享整个项目(例如在 github 上)?这样就更容易看到全貌了。
  • 一些一般性观察: 1) 大多数@Order@DependsOn 声明可能是不必要的——Spring 足够聪明,可以在大多数情况下解决依赖关系。 2) @EnableAspectJAutoProxy 是多余的。 3) 自动配置声明中的所有排除项也可能是多余的,它们肯定会分散注意力。 4) @AutoConfigureAfter 仅适用于自动配置类,而你的(我假设)是普通的组件 bean。
  • Dave,我已经将项目推送到 github:link.
  • @DaveSyer 项目以spring-boot 0.5.0.M5 启动,没有任何错误。由于 M5 使用spring 4.0.0.M3,我尝试运行spring-boot 0.5.0.M6 + spring 4.0.0.M3,但启动失败。但使用spring-boot 0.5.0.M5 + spring 4.0.0.RELEASE 运行正常。
  • 您可以尝试 M7(还有快照)。可能值得一试(我可以看看你的项目到明天)。

标签: java spring-boot configuration nullpointerexception autowired


【解决方案1】:

依赖DataSource 的bean 的急切初始化绝对是问题所在。根本原因与 Spring Boot 或自动配置无关,而是简单的老式鸡和蛋 - 方法安全性是通过由 BeanPostProcessor 包裹在您的业务 bean 周围的方面应用的。 bean 只能由早期初始化的东西进行后期处理非常。在这种情况下,注入DataSource 还为时过早(实际上,需要DataSource@Configuration 类被实例化得太早而无法正确包装在@Configuration 处理机制中,因此无法自动装配)。我的建议(这只会使您与缺少的AuthenticationManager 达到同一点)是将GlobalMethodSecurityConfiguration 声明为嵌套类,而不是需要DataSource 的嵌套类:

@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
protected static class ActualMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {

    @Autowired
    @Qualifier("aclDaoAuthenticationProvider")
    private AuthenticationProvider aclDaoAuthenticationProvider;

    @Autowired
    @Qualifier("aclAnonymousAuthenticationProvider")
    private AnonymousAuthenticationProvider aclAnonymousAuthenticationProvider;

    @Autowired
    @Qualifier("aclExpressionHandler")
    private MethodSecurityExpressionHandler aclExpressionHandler;

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.authenticationProvider(aclDaoAuthenticationProvider);
        auth.authenticationProvider(aclAnonymousAuthenticationProvider);
    }

    @Override
    public MethodSecurityExpressionHandler createExpressionHandler() {
        return aclExpressionHandler;
    }

}

即将其粘贴在 RootMethodSecurityConfiguration 中并从该类中删除 @EnableGlobalMethodSecurity 注释。

【讨论】:

  • Github repo 更新为@DaveSyer 解决方案!还为实体和存储库添加了针对 @PreAuthorize@Transactional 的小测试。
  • 经过数小时的研究,我终于找到了这个答案!现在我的问题是结果,我可以继续我的开发。非常感谢!
【解决方案2】:

我可能已经解决了这个问题。

GlobalMethodSecurityConfiguration.class 具有以下尝试自动装配权限评估器的设置器:

@Autowired(required = false)
public void setPermissionEvaluator(List<PermissionEvaluator> permissionEvaluators) {
    ....
}

在我的情况下,aclPermissionEvaluator() bean 需要 aclService() bean,而这又取决于另一个自动装配属性:dataSource。这似乎还没有自动装配。

为了解决这个问题,我实现了BeanFactoryAware 并从beanFactory 获取dataSource

public class RootMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration implements BeanFactoryAware {

    private DataSource dataSource;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.dataSource = beanFactory.getBean("dataSource", DataSource.class);
    }
    ....
}

在这之后,出现了其他异常,其中SecurityAutoConfiguration.class 抱怨缺少AuthenticationManager,所以我只是将它从@EnableAutoConfiguration 中排除。我不确定它是否理想,但我有自定义安全配置,所以这样一切正常。

【讨论】:

    猜你喜欢
    • 2018-08-25
    • 1970-01-01
    • 2020-10-11
    • 2019-05-19
    • 1970-01-01
    • 2016-02-23
    • 2020-06-14
    • 2017-10-29
    • 1970-01-01
    相关资源
    最近更新 更多