Autowired属性为null - Spring Boot Configuration

时间:2013-12-31 11:42:46

标签: java spring-boot configuration nullpointerexception autowired

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

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

带有bean的四个配置文件位于一个包中,并按“area”排序:

  1. 数据源配置
  2. 全局方法安全配置(因为我们使用Spring-ACL)
  3. MVC配置
  4. Spring Security配置
  5. 引导所有内容的主要方法在以下文件中:

    @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),但这也无济于事。我没有在@Autowired上执行DataSource,而是尝试注入RootDataSourceConfig类本身,但它仍然为空。我们尝试在这些bean上使用@DependsOn@Ordered但是再次没有成功。似乎没有任何东西可以注入这种配置。

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

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

    回购:github

2 个答案:

答案 0 :(得分:4)

依赖于DataSource的bean的急切初始化肯定是个问题。根本原因与Spring Boot或自动配置无关,而是简单的老式鸡和蛋 - 方法安全性通过BeanPostProcessor围绕您的业务bean的方面应用。 bean只能通过早期非常初始化的内容进行后期处理。在这种情况下,注入DataSource为时尚早(实际上需要@Configuration的{​​{1}}类过早实例化,无法在DataSource处理机器中正确包装,所以它不能自动装配)。我的提案(只能让您与缺少的@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注释。

答案 1 :(得分:0)

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

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

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

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

要解决此问题,我实施了BeanFactoryAware并从dataSource获取了beanFactory

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中排除。我不确定它是否理想,但我有自定义安全配置,所以这样一切正常。