问题描述
一段时间以来,我一直在努力解决这个问题,并且浏览了许多文章,但找不到解决方案.感谢您对以下问题的帮助.
I have been struggling with this issue for a while and have browsed a lot of articles, but couldnt figure out the solution. Appreciate your help with the issue below.
我需要能够在服务类中自动装配EntityManager,但是会引发异常.默认的构造函数可能由于类型擦除而存在问题,因此我尝试使用带有参数的构造函数来设置Type.如何自动连接类型为User的EntityManager?
I need to be able to autowire the EntityManager in the service class, but throws an exception. The default constructor probably has issues because of type erasure and so I tried using a constructor with parameters to set the Type. How do I autowire EntityManager of type User?
public interface IEntityManager<T extends IDomain<ID>, ID extends Serializable> {
T findById(ID id, boolean lock);
T save(T entity);
void delete(T entity);
}
public class EntityManager<T extends IDomain<ID>, ID extends Serializable>
implements IEntityManager<T, ID> {
private Class<T> entity;
@Autowired(required=true)
private SessionFactory sessionFactory;
/*
@SuppressWarnings("unchecked")
public EntityManager() {
this.entity = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
} */
@Autowired(required=true)
public EntityManager(Class<T> entity) {
this.entity = entity;
}
}
@Service("UserService")
@Transactional
public class UserServiceImpl implements IUserService {
@Autowired
EntityManager<User, Integer> entityManager;
}
这里是个例外:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'UserService': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.test.dummy.persistence.manager.EntityManager com.test.dummy.service.UserServiceImpl.entityManager; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.test.dummy.persistence.manager.EntityManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
推荐答案
Spring 无法推论它需要在EntityManager
的构造函数中注入User.class
以满足UserServiceImpl
中的依赖性.
Spring cannot deduce that it need to Inject User.class
in the constructor of EntityManager
to satisfy the depdenency in UserServiceImpl
.
如果使用的是 Spring 4 ,则可以定义EntityManager<User, Integer>
类型的Bean:
If you are using Spring 4, You can to define a bean of type EntityManager<User, Integer>
:
@Configuration
public class Config {
@Bean
public EntityManager<User, Integer> userEntityManager() {
new EntityManager(User.class);
}
}
修改:或定义 BeanDefinitionRegistryPostProcessor ,它将检查需要EntityManager作为依赖项的bean,确定所需的类型,为所需的类型构造新的EntityManager bean,并将其添加到bean注册表中.
Or define a BeanDefinitionRegistryPostProcessor that will check for beans that require EntityManager as dependency, identify the required type, construct the new EntityManager bean for the required type and add it to the bean registry.
@Component
public class MyEntityManagerBeanDefinitionRegistryPostProcessor implements
BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory)
throws BeansException {
for (String beanName : beanFactory.getBeanDefinitionNames()) {
final BeanDefinition beanDefinition = getOriginatingBeanDefinition(
beanFactory.getBeanDefinition(beanName));
final Class<?> beanClass = getClass(beanDefinition.getBeanClassName());
if (beanClass != null) {
ReflectionUtils.doWithFields(beanClass, new ReflectionUtils.FieldCallback() {
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
if (field.isAnnotationPresent(Autowired.class) || field.isAnnotationPresent(
Inject.class)) {
if (field.getGenericType() instanceof ParameterizedType) {
final ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
final Class<?> rawType = (Class) parameterizedType.getRawType();
if (rawType.equals(EntityManager.class)) {
final Class<?> typeArgument = (Class<?>) parameterizedType.getActualTypeArguments()[0];
beanFactory.registerSingleton(field.getName(), new EntityManager(typeArgument));
}
}
}
}
});
}
}
}
private Class<?> getClass(String className) throws BeansException {
if (className != null) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
throw new BeanInitializationException("beanClass not found", e);
}
}
return null;
}
private BeanDefinition getOriginatingBeanDefinition(BeanDefinition beanDefinition) {
while(beanDefinition.getOriginatingBeanDefinition() != null) {
beanDefinition = beanDefinition.getOriginatingBeanDefinition();
}
return beanDefinition;
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { }
}
最后,看来您实际需要的是使用 Spring Data Jpa 从本质上讲,您可以通过定义如下接口来定义参数化DAO:
Finally, it looks like what you actually need is to use Spring Data Jpa which, in essence, lets you define a parameterized DAO by defining an interface like this:
package com.myapp.repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {}
您启用它:
@Configuration
@EnableJpaRepositories(basePackages = "com.myapp.repository")
public class Config {
}
然后注入UserRepository
:
@Autowired
private UserRepository userRepository;
Spring将注入一个基本的DAO实现.
And Spring will inject a basic DAO implementation.
这篇关于关于参数化类的Spring自动装配问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!