Java 使用依赖注入实现数据访问API

Java 使用依赖注入实现数据访问API,java,web-services,api,dependency-injection,guice,Java,Web Services,Api,Dependency Injection,Guice,我刚开始编写API,做了一些研究,并意识到要实现我想要的,我需要使用依赖注入来完成。我正在编写一个android应用程序,它有两个数据源。一个是由web服务公开的,另一个是SQLlite。SQLlite在没有可用数据连接的情况下用作备份(目前只有对API的webservice部分感兴趣的才会重构)。我想编写一个API,提供一个抽象层,根据所需模型调用正确的数据访问类。因此,我有一个接口来描述api应该实现的方法,称为IDataAccess(只对getAll感兴趣,目的是为了弄清楚该做什么) ID

我刚开始编写API,做了一些研究,并意识到要实现我想要的,我需要使用依赖注入来完成。我正在编写一个android应用程序,它有两个数据源。一个是由web服务公开的,另一个是SQLlite。SQLlite在没有可用数据连接的情况下用作备份(目前只有对API的webservice部分感兴趣的才会重构)。我想编写一个API,提供一个抽象层,根据所需模型调用正确的数据访问类。因此,我有一个接口来描述api应该实现的方法,称为IDataAccess(只对getAll感兴趣,目的是为了弄清楚该做什么)

IDataAccess的一个实现是(注意,我使用的是Jersey客户端API):

然后我得到了实际的DataAccessManager类:

public class DataAccessManager {
    protected Client client;
    protected DataAccessManager (Client client)n{
        this.client = client;
    }//end constructor 
    public <T>  List <Object> getAll(T t) {
        Data module = new Data ();
        Injector injector = Guice.createInjector(module);
        IDataAccess data = (IDataAccess) injector.getInstance(t.getClass());
        return (List<Object>) data;
    }//end fetchAllUser method
}
公共类DataAccessManager{
受保护的客户端;
受保护的DataAccessManager(客户端)n{
this.client=client;
}//端构造函数
公共列表getAll(T){
数据模块=新数据();
喷油器喷油器=Guice.createInjector(模块);
IDataAccess数据=(IDataAccess)injector.getInstance(t.getClass());
返回(列表)数据;
}//末端取数器方法
}
要在此类上调用用户模型,我将执行以下操作:

@Test
public void fetchUser () {
        DataAccessManager m = DataAccessFactory.getInstance().createDataAccessManager();
        List<User> user = (List<User>)  m.getAll(new Userdata ());
        if (user == null)
            assertEquals(1, 2);
        else
            assertEquals(1, 1);
}
@测试
公共用户(){
DataAccessManager m=DataAccessFactory.getInstance().createDataAccessManager();
List user=(List)m.getAll(newuserdata());
if(user==null)
资产质量(1,2);
其他的
资产质量(1,1);
}
理想情况下,我现在想要做的是,调用UserData来获取所有的用户对象,或者调用OrderData(在编写实现时)类来获取所有的order对象等等

问题在于,这是一个错误:

无法从一个列表强制转换到另一个列表

。如何解决此问题或重新构造此问题,使其有意义?

1)您正在为每个请求创建一个注入器(
Guice.createInjector
)。注入器创建成本很高,通常应在应用程序加载期间完成。您应该将DI视为一种引导机制,并使其保持简单

2) 您不需要DataAccessFactory。首先,不需要工厂,因为createDataAccessManager实例化不需要任何逻辑,其次Guice也可以处理工厂模式

我个人会保持它的简单性,并使用Guice直接将
UserData
实例注入到每个需要它的服务中,而不使用这里显示的相当复杂的抽象方法。不过,它并不能解决处理网络问题的问题。我的猜测是,每个数据访问类都必须以特定的方式处理连接性,因此逻辑应该直接在这里

有关列表转换问题,请参见


如果你继续这样做,我建议你也读一下

这是你经常遇到的问题。我们希望当
String
is-a
Object
时,
List
is-a
List
也是正确的。但事实并非如此。这就是为什么这个类演员不能工作的原因:

@Test
public void fetchUser () {
//...
List<User> user = (List<User>)  m.getAll(new Userdata ());
//..
}
我还要澄清DataAccesManager本身:

public class DataAccessManager<T> {
    //fields and constructors
    public List<T> getAll(IDataAccess<T> access) { //this is how the test suggests you want to use this method
        Data module = new Data ();
        Injector injector = Guice.createInjector(module);
        IDataAccess<T> data = (IDataAccess<T>) injector.getInstance(access.getClass()); //why is this line important? why don't you use the access parameter instead?
        return data.getAll();
    }
}
公共类DataAccessManager{
//字段和构造函数
public List getAll(IDataAccess){//测试建议您使用此方法
数据模块=新数据();
喷油器喷油器=Guice.createInjector(模块);
IDataAccess数据=(IDataAccess)injector.getInstance(access.getClass());//为什么这一行很重要?为什么不使用access参数?
返回data.getAll();
}
}

您使用的是Spring框架还是其他什么?还是你在问自己如何实现DI?我认为后者是个坏主意。
public class DataAccessManager {
    protected Client client;
    protected DataAccessManager (Client client)n{
        this.client = client;
    }//end constructor 
    public <T>  List <Object> getAll(T t) {
        Data module = new Data ();
        Injector injector = Guice.createInjector(module);
        IDataAccess data = (IDataAccess) injector.getInstance(t.getClass());
        return (List<Object>) data;
    }//end fetchAllUser method
}
@Test
public void fetchUser () {
        DataAccessManager m = DataAccessFactory.getInstance().createDataAccessManager();
        List<User> user = (List<User>)  m.getAll(new Userdata ());
        if (user == null)
            assertEquals(1, 2);
        else
            assertEquals(1, 1);
}
@Test
public void fetchUser () {
//...
List<User> user = (List<User>)  m.getAll(new Userdata ());
//..
}
public interface IDataAccess<T> {  
    public List <T> getAll ();  
    public T getById (int id);
}//end  IDataAccess

public class UserData extends DataAccessManager<User> implements IDataAccess<User> {
// your implementation
} 
public class DataAccessManager<T> {
    //fields and constructors
    public List<T> getAll(IDataAccess<T> access) { //this is how the test suggests you want to use this method
        Data module = new Data ();
        Injector injector = Guice.createInjector(module);
        IDataAccess<T> data = (IDataAccess<T>) injector.getInstance(access.getClass()); //why is this line important? why don't you use the access parameter instead?
        return data.getAll();
    }
}