如何在不出现空指针异常的情况下正确注入服务 class?
How can I inject a service class properly without getting nullpointer exception?
我正在开发一个 Spring 引导应用程序,我正在尝试将我的 UserService class 注入我的 TenantIdentifierResolver class 因为我想使用 createUser() 方法。但是我得到一个空指针异常。由于某种原因,userService 设置为 null,我在这里缺少什么?
@Component
public class TenantIdentifierResolver implements CurrentTenantIdentifierResolver {
public static final String DEFAULT_TENANT = "default_schema";
private UserService userService;
@Override
public String resolveCurrentTenantIdentifier() {
String tenant = TenantContext.getCurrentTenant();
if(tenant != null){
userService.createUser(tenant);
return tenant;
} else {
return DEFAULT_TENANT;
}
}
@Override
public boolean validateExistingCurrentSessions() {
return true;
}
}
我尝试使用@Autowired 或进行构造函数注入,但随后出现此错误:
application context中部分bean的依赖关系形成一个循环:
┌─────┐
| entityManagerFactory defined in class path resource [org/example/membership/config/HibernateConfig.class]
↑ ↓
| tenantIdentifierResolver (field private org.example.membership.service.UserService org.example.membership.multitenancy.TenantIdentifierResolver.userService)
↑ ↓
| userService defined in file [C:\project\Member\server\target\classes\org\example\membership\service\UserService.class]
↑ ↓
| userRepository defined in org.example.membership.repository.UserRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration
↑ ↓
| (inner bean)#18957a3d
└─────┘
这是我的 UserService class
@Service
public class UserService {
private UserRepository userRepository;
private TenantService tenantService;
public UserService(UserRepository repository, TenantService tenantService) {
this.userRepository = repository;
this.tenantService = tenantService;
}
@Transactional
public User createUser(String tenant) {
Tenant tenant = new Tenant();
tenant.setTenantName(tenant);
tenantService.initDatabase(tenant);
return tenant ;
}
}
这是我的 HibernateConfig class
@Configuration
public class HibernateConfig {
@Autowired
private JpaProperties jpaProperties;
@Bean
JpaVendorAdapter jpaVendorAdapter() {
return new HibernateJpaVendorAdapter();
}
@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory(
DataSource dataSource,
MultiTenantConnectionProvider multiTenantConnectionProviderImpl,
CurrentTenantIdentifierResolver currentTenantIdentifierResolverImpl
) {
Map<String, Object> jpaPropertiesMap = new HashMap<>(jpaProperties.getProperties());
jpaPropertiesMap.put(Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
jpaPropertiesMap.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProviderImpl);
jpaPropertiesMap.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolverImpl);
LocalContainerEntityManagerFactoryBean em = new
LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("org.example*");
em.setJpaVendorAdapter(this.jpaVendorAdapter());
em.setJpaPropertyMap(jpaPropertiesMap);
return em;
}
}
您没有注入依赖项。您应该使用构造函数注入:
private final UserService userService;
public TenantIdentifierResolver(UserService userService) {
this.userService = userService;
}
或者,如果您愿意,可以使用属性注入:
@Autowired
private UserService userService;
您在这里遇到的问题称为循环依赖。当两个组件需要彼此的 bean 时,就会发生这种情况。 Spring不知道先创建哪个。您可以在此处阅读更多相关信息 www.netjstech.com/2018/03/circular-dependency-in-spring-framework.html
Easiset 解决方案是在其中一个组件中实施基于 setter 的自动布线。
@Component
public class TenantIdentifierResolver {
private UserService userService;
public UserService userService() {
return userService;
}
@Autowired
public void setUserService(final UserService userService) {
this.userService = userService;
}
}
最后你必须解决循环依赖,无论你使用什么注入类型,或者如果你诉诸惰性注入等等
目前您的 entityManagerFactory 需要 userService bean(通过 tenantIdentifierResolver),它本身需要 entityManagerFactory。那是一个糟糕的架构。您可以从 tenantIdentifierResolver 中删除对 userService 的调用,或者更改它以便在那里不使用与 JPA 相关的功能(即,如果您确实需要即时创建 tenants/users,请使用纯 JDBC在那里打电话)。那么你已经打破了依赖循环,一切都应该工作。
@Autowired
private UserService userService;
至于循环依赖问题,我觉得你应该尽量避免。
我正在开发一个 Spring 引导应用程序,我正在尝试将我的 UserService class 注入我的 TenantIdentifierResolver class 因为我想使用 createUser() 方法。但是我得到一个空指针异常。由于某种原因,userService 设置为 null,我在这里缺少什么?
@Component
public class TenantIdentifierResolver implements CurrentTenantIdentifierResolver {
public static final String DEFAULT_TENANT = "default_schema";
private UserService userService;
@Override
public String resolveCurrentTenantIdentifier() {
String tenant = TenantContext.getCurrentTenant();
if(tenant != null){
userService.createUser(tenant);
return tenant;
} else {
return DEFAULT_TENANT;
}
}
@Override
public boolean validateExistingCurrentSessions() {
return true;
}
}
我尝试使用@Autowired 或进行构造函数注入,但随后出现此错误:
application context中部分bean的依赖关系形成一个循环:
┌─────┐
| entityManagerFactory defined in class path resource [org/example/membership/config/HibernateConfig.class]
↑ ↓
| tenantIdentifierResolver (field private org.example.membership.service.UserService org.example.membership.multitenancy.TenantIdentifierResolver.userService)
↑ ↓
| userService defined in file [C:\project\Member\server\target\classes\org\example\membership\service\UserService.class]
↑ ↓
| userRepository defined in org.example.membership.repository.UserRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration
↑ ↓
| (inner bean)#18957a3d
└─────┘
这是我的 UserService class
@Service
public class UserService {
private UserRepository userRepository;
private TenantService tenantService;
public UserService(UserRepository repository, TenantService tenantService) {
this.userRepository = repository;
this.tenantService = tenantService;
}
@Transactional
public User createUser(String tenant) {
Tenant tenant = new Tenant();
tenant.setTenantName(tenant);
tenantService.initDatabase(tenant);
return tenant ;
}
}
这是我的 HibernateConfig class
@Configuration
public class HibernateConfig {
@Autowired
private JpaProperties jpaProperties;
@Bean
JpaVendorAdapter jpaVendorAdapter() {
return new HibernateJpaVendorAdapter();
}
@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory(
DataSource dataSource,
MultiTenantConnectionProvider multiTenantConnectionProviderImpl,
CurrentTenantIdentifierResolver currentTenantIdentifierResolverImpl
) {
Map<String, Object> jpaPropertiesMap = new HashMap<>(jpaProperties.getProperties());
jpaPropertiesMap.put(Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
jpaPropertiesMap.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProviderImpl);
jpaPropertiesMap.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolverImpl);
LocalContainerEntityManagerFactoryBean em = new
LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("org.example*");
em.setJpaVendorAdapter(this.jpaVendorAdapter());
em.setJpaPropertyMap(jpaPropertiesMap);
return em;
}
}
您没有注入依赖项。您应该使用构造函数注入:
private final UserService userService;
public TenantIdentifierResolver(UserService userService) {
this.userService = userService;
}
或者,如果您愿意,可以使用属性注入:
@Autowired
private UserService userService;
您在这里遇到的问题称为循环依赖。当两个组件需要彼此的 bean 时,就会发生这种情况。 Spring不知道先创建哪个。您可以在此处阅读更多相关信息 www.netjstech.com/2018/03/circular-dependency-in-spring-framework.html
Easiset 解决方案是在其中一个组件中实施基于 setter 的自动布线。
@Component
public class TenantIdentifierResolver {
private UserService userService;
public UserService userService() {
return userService;
}
@Autowired
public void setUserService(final UserService userService) {
this.userService = userService;
}
}
最后你必须解决循环依赖,无论你使用什么注入类型,或者如果你诉诸惰性注入等等
目前您的 entityManagerFactory 需要 userService bean(通过 tenantIdentifierResolver),它本身需要 entityManagerFactory。那是一个糟糕的架构。您可以从 tenantIdentifierResolver 中删除对 userService 的调用,或者更改它以便在那里不使用与 JPA 相关的功能(即,如果您确实需要即时创建 tenants/users,请使用纯 JDBC在那里打电话)。那么你已经打破了依赖循环,一切都应该工作。
@Autowired
private UserService userService;
至于循环依赖问题,我觉得你应该尽量避免。