能有一个用Guice来实例化/注入一个DataSource,或者第三方对象的例子么?
比如在Spring的环境下可以如下配置:
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
...
2
sa
...
Dhanji R.Prasanna————
你可以创建一个Provider来满足这个需求并且配置其中的值:
public class BDSProvider implements Provider {
@Inject @Named("ds.initial_size") int initialSize;
@Inject @Named("ds.username") String username;
//..
public BasicDataSource get() {
BasicDataSource source = new BasicDataSource();
source.setInitialSize(initialSize);
source.setUsername(username);
//...etc.
return source;
}
}
然后把该provider绑定:
bind(BasicDataSource.class).toProvider(BDSProvider.class);
接着可以从某个配置文件(properties)中配置
bindProperties()....
jfz————
下面是一个能工作的代码,他有什么设计问题?
protected void configure() {
...
final BasicDataSource bds = new BasicDataSource();
bds.setUrl("url");bds.setUsername("uName");...
bind(BasicDataSource.class).toInstance(bds);
...
}
Dhanji R.Prasanna————
虽然他能工作,但意味着:
1,BDS现在是一个singleton的了
2,BDS是迫切的初始化(eagerly instantiated)
3,你将模块的绑定和工厂代码混淆在一起了
4,你将url,username等应该放在一个非文件的东西用于实例化了。
讨论到这里,并没有给一个全面的使用Provider的示例,
下面给出一个我使用Provider的测试:
首先模拟一个DataSource:
package com.easyjf.guicUse.third;
public class MockDataBase {
private String userName;
private String password;
private int initialNum;
public int getInitialNum() {
return initialNum;
}
public void setInitialNum(int initialNum) {
this.initialNum = initialNum;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String connect(){
return this.initialNum+this.userName+this.password;
}
}
然后创建一个Porvider来代理
package com.easyjf.guicUse.third;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.name.Named;
public class BDSProvider implements Provider{
@Inject
@Named("ds.initial_size")
int initialSize;
@Inject
@Named("ds.userName")
String userName;
@Inject
@Named("ds.password")
String password;
public MockDataBase get(){
MockDataBase source=new MockDataBase();
source.setInitialNum(this.initialSize);
source.setUserName(userName);
source.setPassword(password);
return source;
}
}
接着创建一个mockDao来使用该DataSource:
package com.easyjf.guicUse.third;
import com.google.inject.Inject;
import com.google.inject.Provider;
public class MockDao {
private MockDataBase dataSource;
@Inject
public MockDao(Provider provider){
dataSource = provider.get();
}
public String go(){
return dataSource.connect();
}
}
然后是一个Module来绑定该Provider:
package com.easyjf.guicUse.third;
import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;
import com.google.inject.AbstractModule;
import com.google.inject.name.NamedImpl;
public class MyModule extends AbstractModule {
private int num;
private String userName;
private String password;
public MyModule() throws Exception{
Properties properties=new Properties();
File file=new File("config.properties");
properties.load(new FileInputStream(file));
this.num=Integer.parseInt(properties.getProperty("ds.initial_size"));
this.userName=properties.getProperty("ds.userName");
this.password=properties.getProperty("ds.password");
}
@Override
protected void configure() {
// TODO Auto-generated method stub
bind(MockDataBase.class).toProvider(BDSProvider.class);
this.bind(int.class).annotatedWith(Names.named("ds.initial_size")).toInstance(num);
this.bind(String.class).annotatedWith(Names.named("ds.userName")).toInstance(userName);
this.bind(String.class).annotatedWith(Names.named("ds.password")).toInstance(password);
}
}
这里把参数放在了一个config.properties文件里面
下面是测试:
package com.easyjf.guicUse.third;
import junit.framework.TestCase;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class DaoTest extends TestCase {
public void testGo() throws Exception{
Injector injector=Guice.createInjector(new MyModule());
MockDao dao=new MockDao(injector.getProvider(MockDataBase.class));
assertEquals("1stefpassword",dao.go());
}
}