[英]Generic Java service with programmatic bean creation does not inject EntityManager
我有一个(希望)标准设置,带有一堆@Controller
, @Service
@Controller
, @Service
@Entity
和@Repository
注释类,例如:
@Service
public class ChannelManager {
@Autowired
private ChannelDao channelDao;
public List<Channel> allChannels() {
return channelDao.findAll();
}
}
ChannelDao
在哪里:
public interface ChannelDao extends PersistentDao<Channel> {}
ChannelImpl
是:
@Repository
public class ChannelImpl extends PersistentImpl<Channel> implements ChannelDao {}
Channel
是:
@Entity
@Table(name = "channel")
public class Channel extends Persistent {
@Id
@Column(name = "id", nullable = false)
private Long id;
// set/get
}
PersistentDao
是:
public interface PersistentDao<T extends Persistent> {
public List<T> findAll();
}
最后PersistentImpl
是:
public class PersistentImpl<T extends Persistent> implements PersistentDao<T> {
@PersistenceContext
protected EntityManager entityManager;
private Class<T> clazz; // gets assigned correctly
public List<T> findAll() {
return entityManager.createQuery("from " + clazz.getSimpleName()).getResultList();
}
}
所有这一切都按预期进行。 我正在使用<context:annotation-config/>
和<context:component-scan/>
以及<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" ...>
与persistence.xml
。 基本上所有的工作。
但是现在我要归纳ChannelManager,因为我还有许多其他实体,并且希望避免重复。 例如,我还需要一个具有List<Job> allJobs() { return jobDao.findall(); }
List<Job> allJobs() { return jobDao.findall(); }
方法。
所以我创建了这个:
@Service
public class GeneralManager<T extends PersistentDao, E extends Persistent> {
@Autowired
private AutowireCapableBeanFactory factory;
public void setFactory(AutowireCapableBeanFactory factory) {
this.factory = factory;
}
private Class<? extends T> impl;
private T dao;
public GeneralManager(Class<? extends T> impl) throws Exception {
this.impl = impl;
}
@PostConstruct
public void postCtor() {
dao = factory.createBean(impl); // seems to be created and is not null
}
public List<E> all() {
return dao.findAll();
}
}
我更新了context.xml
<bean id="jobImpl" class="a.b.c.GeneralManager">
<property name="factory" ref="autowireFactory"/>
<constructor-arg value="a.b.c.JobImpl"/>
</bean>
<bean id="autowireFactory" class="org.springframework.beans.factory.support.DefaultListableBeanFactory"/>
<context:annotation-config/>
<context:component-scan base-package="a.b.c">
<context:exclude-filter type="regex" expression=".*GeneralManager"/>
</context:component-scan>
最后在控制器中添加了一个声明:
@Autowired
@Qualifier(value="jobImpl")
private GeneralManager<JobDao, Job> jobManager;
试想一下Jobxxx类与Channelxxx类相似。
但是,当要执行JobImpl
专业化中的findAll()
方法时,entityManager为null ,因此未正确设置某些内容。
所以我的问题确实是“可以做到吗”? 尽管如果有另一种更好的方法可以这样做,请赐教!
编辑:可能要注意的是,我正在使用Spring 3.0.5,Java 1.6.0_21-b07和Hibernate 3.6.2。
因此,在对它进行了更多思考之后,我通过明确定义bean来朝一个略有不同的方向发展,这是我试图避免的事情。 但这对我有用。 我仍然不知道我试图做的事情是否由于类型擦除而无法实现。
我的代码现在看起来像:
public class GeneralManager<T extends PersistentDao, E extends Persistent> {
private T dao;
public void setDao(T dao) {
this.dao = dao;
}
...
}
使用以下控制器:
@Autowired
private GeneralManager<ChannelDao, Channel> channelManager;
@Autowired
private GeneralManager<JobDao, Job> jobManager;
和context.xml现在具有:
<bean id="jobManager" class="com.a.b.service.EntityManager" p:dao-ref="jobImpl"/>
<bean id="jobImpl" class="com.a.b.dao.JobImpl"/>
<bean id="channelManager" class="com.a.b.service.EntityManager" p:dao-ref="channelImpl"/>
<bean id="channelImpl" class="com.a.b.dao.ChannelImpl"/>
希望这对某人有帮助!
为什么不简单地使用spring-data项目呢? 它完全满足您的需求,而且功能更多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.