Autowired 属性为空 - Spring Boot 配置 [英] Autowired property is null - Spring Boot Configuration
问题描述
我在自动装配的属性中遇到了空值.我希望我能得到一些帮助.
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":
- 数据源配置
- 全局方法安全配置(因为我们使用 Spring-ACL)
- MVC 配置
- 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屋!