Autowired 属性为空 - Spring Boot 配置 [英] Autowired property is null - Spring Boot Configuration

查看:94
本文介绍了Autowired 属性为空 - Spring Boot 配置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am stuck with null values in an autowired property. I am hoping I could get some help.

我们用于项目 spring-boot 版本 0.5.0.M6.

We are using for the project spring-boot version 0.5.0.M6.

带bean的四个配置文件在一个包中,按区域"排序:

The four configuration files with beans are in one package and are sorted by "area":

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

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

The main method that bootstraps everything is in the following file:

@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的第一个文件如下(我省略了一些方法体部分以使其更具可读性):

The first file that holds the data source configuration beans is as follows (I have omitted some method body parts to make it more readable):

@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 上失败:

And here is the next configuration file, that depends on the data source from above. It has about 20 beans related to ACL configuration, but it fails on the firsts bean that uses data source:

@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 但同样没有成功.好像什么都不能注入到这个配置中.

Basically invoking aclService() throws an error as dataSource is null. We have tried ordering the configuration files by implementing the Ordered interface. We also tried using @AutoConfigureAfter(RootDataSourceConfig.class) but this did not help either. Instead of doing @Autowired on the DataSource we also tried injecting the RootDataSourceConfig class itself, but it was still null. We tried using @DependsOn and @Ordered on those beans but again no success. It seems like nothing can be injected into this configuration.

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

The console output at the startup is listing the beans in the order we want them, with data source being the first. We are pretty much blocked by this.

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

Is there anything weird or unique we are doing here that is not working? If this is as designed, then how could we inject data source differently?

回购:github

推荐答案

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

Eager initialization of a bean that depends on a DataSource is definitely the problem. The root cause is nothing to do with Spring Boot or autoconfiguration, but rather plain old-fashioned chicken and egg - method security is applied via an aspect which is wrapped around your business beans by a BeanPostProcessor. A bean can only be post processed by something that is initialized very early. In this case it is too early to have the DataSource injected (actually the @Configuration class that needs the DataSource is instantiated too early to be wrapped properly in the @Configuration processing machinery, so it cannot be autowired). My proposal (which only gets you to the same point with the missing AuthenticationManager) is to declare the GlobalMethodSecurityConfiguration as a nested class instead of the one that the DataSource is needed in:

@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 注释.

i.e. stick that inside the RootMethodSecurityConfiguration and remove the @EnableGlobalMethodSecurity annotation from that class.

这篇关于Autowired 属性为空 - Spring Boot 配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆