弹簧 3.2 自动线通用类型

所以我在Spring 3.2中有许多泛型,理想情况下,我的架构看起来像这样。

class GenericDao<T>{}

class GenericService<T, T_DAO extends GenericDao<T>>
{
    // FAILS
    @Autowired
    T_DAO;
}

@Component
class Foo{}

@Repository
class FooDao extends GenericDao<Foo>{}

@Service
FooService extends GenericService<Foo, FooDao>{}

不幸的是,对于泛型的多个实现,自动布线会引发有关多个匹配的Bean定义的错误。我认为这是因为类型擦除之前的过程。我发现或想出的每一个解决方案对我来说都很丑陋,或者只是莫名其妙地拒绝工作。解决这个问题的最佳方法是什么?@Autowired


答案 1

如何将构造函数添加到 中,并将自动布线移动到扩展类,例如GenericService

class GenericService<T, T_DAO extends GenericDao<T>> {
    private final T_DAO tDao;

    GenericService(T_DAO tDao) {
        this.tDao = tDao;
    }
}

@Service
FooService extends GenericService<Foo, FooDao> {

    @Autowired
    FooService(FooDao fooDao) {
        super(fooDao);
    }
}

更新:

Spring 4.0 RC1开始,可以基于通用类型自动布线,这意味着您可以编写一个通用服务,例如

class GenericService<T, T_DAO extends GenericDao<T>> {

    @Autowired
    private T_DAO tDao;
}

并创建多种不同的春豆,如:

@Service
class FooService extends GenericService<Foo, FooDao> {
}

答案 2

这是一个最接近的解决方案。专用 DAO 在业务层进行注释。与OP的问题一样,最好的努力是在EntityDAO通用模板本身中有一个带注释的DAO。类型擦除似乎不允许将专用类型信息传递到弹簧工厂[导致报告来自所有专用DAO的匹配豆]

通用实体 DAO 模板

public class EntityDAO<T> 
{
    @Autowired
    SessionFactory factory;

    public Session getCurrentSession()
    {
        return factory.getCurrentSession();
    }

    public void create(T record)
    {
        getCurrentSession().save(record);
    }

    public void update(T record)
    {
        getCurrentSession().update(record);
    }

    public void delete(T record)
    {
        getCurrentSession().delete(record);
    }

    public void persist(T record)
    {
        getCurrentSession().saveOrUpdate(record);
    }

    public T get(Class<T> clazz, Integer id)
    {
        return (T) getCurrentSession().get(clazz, id);
    }
}

基于通用实体的业务层模板

public abstract class EntityBusinessService<T>
implements Serializable
{
    public abstract EntityDAO<T> getDAO();

    //Rest of code.
}

一个专门的实体 DAO 示例

@Transactional
@Repository
public class UserDAO
extends EntityDAO<User>
{
}

一个示例专用实体业务类

@Transactional
@Service
@Scope("prototype")
public class UserBusinessService
extends EntityBusinessService<User>
{
    @Autowired
    UserDAO dao;

    @Override
    public EntityDAO<User> getDAO() 
    {
        return dao;
    }

    //Rest of code
}

推荐