通用autowire失败,没有定义bean

时间:2015-10-01 23:07:44

标签: java spring spring-mvc abstract-class

这有点长,但我只是想用spring 4.1.7来学习花哨的东西

我面临的问题是Spring并不喜欢在Reader和Writer控制器中没有为R和W声明bean。一切都编译但在运行时没有任何作用,我得到错误

Error creating bean with name 'userController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: protected carefree.coding.dao.CommerceReaderDAO carefree.coding.controllers.rest.CommerceReaderController.reader; nested exception is java.lang.IllegalArgumentException: Can not set carefree.coding.dao.CommerceReaderDAO field carefree.coding.controllers.rest.CommerceReaderController.reader to com.sun.proxy.$Proxy57

我有一个简单的DAO类

@MappedSuperclass
public abstract class CommerceObject
{
    public enum Type
    {
        USER
    }

    @Transient
    protected Type type;

    @Id
    @GeneratedValue
    @Column(name = "id")
    protected long id;

    public CommerceObject(Type type)
    {
        this.type = type;
        setId(-1l);
    }

    public Type getType()
    {
        return type;
    }

    public long getId()
    {
        return id;
    }

    public void setId(long id)
    {
        this.id = id;
    }

    public boolean equals(CommerceObject object)
    {
        return getId() == object.getId() && getType().equals(object.getType());
    }

    @Override
    public String toString()
    {
        return new Gson().toJson(this);
    }

    public CommerceObject fromString(String json)
    {
        return new Gson().fromJson(json, getClass());
    }

    public abstract boolean update(CommerceObject object);

    public abstract CommerceObject copy();

    @Override
    public int hashCode()
    {
        throw new UnsupportedOperationException("No hashing for game objects");
    }
}

扩展
@Entity(name = "user")
public class User extends CommerceObject
{
    @Column(name = "email")
    private String email;

    public User()
    {
        super(Type.USER);
    }

    public String getEmail()
    {
        return email;
    }

    public void setEmail(String email)
    {
        this.email = email;
    }

    @Override
    public boolean update(CommerceObject object)
    {
        if (object instanceof User)
        {
            User user = (User) object;
            if (equals(user))
            {
                user.setEmail(email);
            }
        }
        return false;
    }

    @Override
    public CommerceObject copy()
    {
        User user = new User();
        user.setEmail(getEmail());
        return user;
    }
}

为了读取和写入数据库,我有两个接口

阅读器

public interface CommerceReaderInterface<V extends CommerceObject>
{
    @Transactional(readOnly = true)
    List<V> get();

    @Transactional(readOnly = true)
    V get(long id);
}

作家

public interface CommerceWriterInterface<V extends CommerceObject>
{
    @Transactional
    V add(V v);

    @Transactional
    V update(V v);

    @Transactional
    V delete(V v);
}

基本数据库访问类

public abstract class CommerceDAO
{
    protected SessionFactory sessionFactory;
    protected Class aClass;

    public CommerceDAO(SessionFactory sessionFactory, Class aClass)
    {
        this.sessionFactory = sessionFactory;
        this.aClass = aClass;
    }
}

允许读者和作者存在

阅读器

public class CommerceReaderDAO<V extends CommerceObject> extends CommerceDAO implements CommerceReaderInterface<V>
{
    public CommerceReaderDAO(SessionFactory sessionFactory, Class aClass)
    {
        super(sessionFactory, aClass);
    }

    @Override
    public List<V> get()
    {
        ClassMetadata hibernateMetadata = sessionFactory.getClassMetadata(aClass);
        if (hibernateMetadata == null)
        {
            return null;
        }
        if (hibernateMetadata instanceof AbstractEntityPersister)
        {
            AbstractEntityPersister persister = (AbstractEntityPersister) hibernateMetadata;
            String tableName = persister.getTableName();
            if (tableName != null)
            {
                return sessionFactory.getCurrentSession().
                        createQuery(tableName).list();
            }
        }
        return null;
    }

    @Override
    public V get(long id)
    {
        V object = (V) sessionFactory.getCurrentSession().
                get(aClass, id);
        Hibernate.initialize(object);
        return object;
    }
}

作家

public class CommerceWriterDAO<V extends CommerceObject> extends CommerceDAO implements CommerceWriterInterface<V>
{
    public CommerceWriterDAO(SessionFactory sessionFactory, Class aClass)
    {
        super(sessionFactory, aClass);
    }

    @Override
    public V add(V v)
    {
        if (v != null)
        {
            sessionFactory.getCurrentSession().save(v);
            return v;
        }
        return null;
    }

    @Override
    public V update(V v)
    {
        if (v != null)
        {
            sessionFactory.getCurrentSession().update(v);
            return v;
        }
        return null;
    }

    @Override
    public V delete(V v)
    {
        if (v != null)
        {
            sessionFactory.getCurrentSession().delete(v);
            sessionFactory.getCurrentSession().flush();
            return v;
        }
        return null;
    }
}

对于控制器,我决定做同样的事情,并有一个读写器界面

阅读器

public interface CommerceReaderInterface
{
    @RequestMapping(value = "/get",
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_VALUE)
    ResponseEntity<String> get();

    @RequestMapping(value = "/get/{id}",
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_VALUE)
    ResponseEntity<String> get(@PathVariable long id);
}

作家

public interface CommerceWriterInterface<V extends CommerceObject>
{
    @RequestMapping(value = "/add",
            method = RequestMethod.POST,
            produces = MediaType.APPLICATION_JSON_VALUE)
    ResponseEntity<String> add(@RequestBody V v);

    @RequestMapping(value = "/update",
            method = RequestMethod.POST,
            produces = MediaType.APPLICATION_JSON_VALUE)
    ResponseEntity<String> update(@RequestBody V v);

    @RequestMapping(value = "/delete",
            method = RequestMethod.POST,
            produces = MediaType.APPLICATION_JSON_VALUE)
    ResponseEntity<String> delete(@RequestBody V v);
}

它们正常实施

阅读器

public abstract class CommerceReaderController<R extends CommerceReaderDAO<V>, V extends CommerceObject> implements CommerceReaderInterface
{
    @Autowired
    protected R reader;

    @Override
    public ResponseEntity<String> get()
    {
        List<V> list = reader.get();
        if (list == null || list.isEmpty())
        {
            return ResponseUtil.notFound();
        }
        return ResponseUtil.ok(list);
    }

    @Override
    public ResponseEntity<String> get(@PathVariable long id)
    {
        V object = reader.get(id);
        if (object == null)
        {
            return ResponseUtil.notFound();
        }
        return ResponseUtil.ok(object);
    }
}

作家

public abstract class CommerceWriterController<W extends CommerceWriterDAO<V>, R extends CommerceReaderDAO<V>, V extends CommerceObject> extends CommerceReaderController<R, V> implements CommerceWriterInterface<V>
{
    @Autowired
    protected W writer;

    @Override
    public ResponseEntity<String> add(@RequestBody V v)
    {
        v = writer.add(v);
        if (v == null)
        {
            return ResponseUtil.notFound();
        }
        return ResponseUtil.ok(v);
    }

    @Override
    public ResponseEntity<String> update(@RequestBody V v)
    {
        v = writer.update(v);
        if (v == null)
        {
            return ResponseUtil.notFound();
        }
        return ResponseUtil.ok(v);
    }

    @Override
    public ResponseEntity<String> delete(@RequestBody V v)
    {
        v = writer.delete(v);
        if (v == null)
        {
            return ResponseUtil.notFound();
        }
        return ResponseUtil.ok(v);
    }
}

在完成所有这些工作后,我认为允许使用简单的控制器

@Controller
@RequestMapping("/commerce/api/user")
public class UserController extends CommerceWriterController<UserWriterDAO, UserReaderDAO, User>
{
}

然而,正如我在抽象控制器中所理解的那样,我不允许有这样模糊的DAO对象。有什么办法可以绕过这个吗?

0 个答案:

没有答案