У меня (надеюсь) стандартная установка с кучей @Controller
, @Service
, @Entity
и @Repository
аннотированных классов, например:
@Service
public class ChannelManager {
@Autowired
private ChannelDao channelDao;
public List<Channel> allChannels() {
return channelDao.findAll();
}
}
где ChannelDao
is:
public interface ChannelDao extends PersistentDao<Channel> {}
ChannelImpl
is:
@Repository
public class ChannelImpl extends PersistentImpl<Channel> implements ChannelDao {}
Channel
is:
@Entity
@Table(name = "channel")
public class Channel extends Persistent {
@Id
@Column(name = "id", nullable = false)
private Long id;
// set/get
}
PersistentDao
is:
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, так как у меня есть много других сущностей и я хочу избежать дублирования.Например, мне также нужен JobManager с методом 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.
Однако, когда дело доходит до выполнения метода findAll()
вДля специализации JobImpl
entityManager равен null , поэтому что-то настроено неправильно.
Итак, мой вопрос действительно заключается в том, "можно ли это сделать"?Хотя, если есть альтернативный и более хороший способ сделать это, пожалуйста, просветите меня!
Редактировать: Следует отметить, что я использую Spring 3.0.5, Java 1.6.0_21-b07и Hibernate 3.6.2.Final