Guice的TypeLiteral如何克服Java泛型类型擦除过程?
它创造了奇迹,但这是如何实现的?
假设我有一个Guice模块ProdModule,我想依赖其他GuiceModule,ProdDbModule和ProdPubSubModule.我如何实现ProdModule的configure()?
我有一个webapp,需要使用Tomcat 7 Web套接字.
在这个webapp中,所有标准的Servlet(扩展的javax.servlet.http.HttpServlet)都能很好地(和正确地)与Google Guice一起工作.为了让我的Servlet与Guice处理程序一起使用,我只需:
@SingletonProvider为MyHandler例如&产生被标记为注入一个setter@Inject举例说明以上几点:
@Singleton
public class MyServlet extends HttpServlet {
private Provider<MyHandler> myHandler;
@Inject
MyServlet() {
}
@Override
protected void service(..) throws ServletException { ... }
@Inject
public void setMyHandler(Provider<MyHandler> myHandler) {
this.myHandler = myHandler;
}
...
}
Run Code Online (Sandbox Code Playgroud)
如何调用同一个Guice处理程序,上面调用myHandler了一个WebSocketServlet?
我不能采用与标准servlet用例相同的样式,因为不是像标准servlet那样拥有Singleton servlet,每个WebSocket通信都会导致实例扩展MessageInbound; 然后MyHandler从MessageInbound实例中的方法(例如onOpen或onClose)调用将调用的适当方法; 不是来自上述HttpServlet实例中的方法MyServlet.
我尝试了什么?我确实尝试了一些(概念上错误的)解决方案,例如从MessageInbound实例中调用websocket-servlet的处理程序; …
我(我想)理解依赖注入的目的,但我只是不明白为什么我需要Guice这样做(好吧,显然我不需要 Guice,但我的意思是为什么使用它会有好处).假设我有现有的(非Guice)代码,它是这样的:
public SomeBarFooerImplementation(Foo foo, Bar bar) {
this.foo = foo;
this.bar = bar;
}
public void fooThatBar() {
foo.fooify(bar);
}
Run Code Online (Sandbox Code Playgroud)
在某个更高级别,也许在我的main()中,我有:
public static void main(String[] args) {
Foo foo = new SomeFooImplementation();
Bar bar = new SomeBarImplementation();
BarFooer barFooer = new SomeBarFooerImplementation(foo, bar);
barFooer.fooThatBar();
}
Run Code Online (Sandbox Code Playgroud)
现在我基本上得到了依赖注入的好处,对吧?更容易测试等等?当然,如果你想要,你可以轻松地更改main()以从配置而不是硬编码中获取实现类名.
据我了解,在Guice做同样的事情,我会做类似的事情:
public SomeModule extends AbstractModule {
@Override
protected void configure() {
bind(Foo.class).to(SomeFooImplementation.class);
bind(Bar.class).to(SomeBarImplementation.class);
bind(BarFooer.class).to(SomeBarFooerImplementation.class);
}
}
@Inject
public SomeBarFooerImplementation(Foo foo, Bar, bar) {
this.foo = foo;
this.bar = bar;
}
public static …Run Code Online (Sandbox Code Playgroud) 我有一个需要一些的模块Depedency.是否可以注入模块本身?我意识到这有点鸡蛋和鸡蛋的情况......
例:
public class MyModule implements Module {
private final Dependency d_;
@Inject public MyModule(Dependency d) {
d_ = d;
}
public void configure(Binder b) { }
@Provides Something provideSomething() {
// this requires d_
}
}
Run Code Online (Sandbox Code Playgroud)
我想在这种情况下,解决方案是将@Provides方法转变为一个完整的Provider<Something>类.这显然是一个简化的例子; 我正在处理的代码有很多这样的@Provides方法,所以将它们分成各个Provider<...>类并引入一个模块来配置它们会增加相当多的混乱 - 我认为Guice是关于减少样板杂乱的一切?
也许这反映了我对Guice的相对苛刻,但我遇到了一些我很想做上述事情的案例.我肯定错过了什么...
我正在使用guice进行依赖注入,而不是aopalliance.我无法弄清楚什么是aopalliance所有关于谁以及谁实现了他们的sourceforge页面上的版本(日期为2004年).为什么guice使用这个版本而不是像AspectJ这样更知名的包?
另外,你知道关于aopalliance版本的任何教程吗?
谢谢
我在一个非常复杂且具有很多业务逻辑的android项目中使用guice进行辩论.Guice似乎很合适,但每当我开始深入阅读它时,它开始看起来比它需要的更复杂.
我不明白的一件事是:如果Guice是如此伟大并且是编写java代码的最佳方式,那么为什么使用Guice的Android代码如此之少......为什么Google没有在内部使用guice来安装Android?
考虑一组MVP-ish类型.存在一个抽象的Presenter,带有View接口:
public interface View {
//...
}
public abstract class AbstractPresenter<V extends View> {
@Inject V view;
//...
}
Run Code Online (Sandbox Code Playgroud)
然后,让我们有一个特定的具体的presenter子类,其视图接口和实现:
public interface LoginView extends View {
//...
}
public LoginPresenter extends AbstractPresenter<LoginView> {
//...
}
public class LoginViewImpl implements LoginView {
//...
}
Run Code Online (Sandbox Code Playgroud)
在Dagger模块中,我们当然会定义一个@Provides方法:
@Provides
LoginView provideLoginView() {
return new LoginViewImpl();
}
Run Code Online (Sandbox Code Playgroud)
在Guice你可以用同样的方式写这个,或者只是bind(LoginView.class).to(LoginViewImpl.class).
但是,在Dagger(来自Google的v1和2.0-SNAPSHOT)中,这会产生错误,因为它无法弄清楚V创建绑定布线时的情况AbstractPresenter<V>.另一方面,Guice指出,因为它实际上是在创建一个LoginPresenter,所以它需要一个实现LoginView.
匕首1.2.2:
foo.bar.AbstractPresenter$$InjectAdapter.java:[21,31] cannot find symbol
symbol: class V
location: class foo.bar.AbstractPresenter$$InjectAdapter
Run Code Online (Sandbox Code Playgroud)
Dagger 2.0-SNAPSHOT:
Caused …Run Code Online (Sandbox Code Playgroud) 我不知道如何以GuiceApplicationBuilder这种方式配置,我能够加载需要DatabaseConfigProvider注入的控制器.
我想指定一个替代的postgres数据库用于测试,或者在内存数据库中指定(如果可能的话).
码
class User
extends MySpecs
with OneAppPerTest
{
override def newAppForTest( testData: TestData ) = new GuiceApplicationBuilder()
// Somehow bind a database here, I guess?
.build()
"A test" should "test" in
{
val result = Application.instanceCache[api.controller.User]
.apply( app )
.list()( FakeRequest() )
...
}
}
Run Code Online (Sandbox Code Playgroud)
堆栈跟踪
[info] - should return an entity *** FAILED ***
[info] com.google.inject.ConfigurationException: Guice configuration errors:
[info]
[info] 1) No implementation for play.api.db.slick.DatabaseConfigProvider was bound.
[info] while locating …Run Code Online (Sandbox Code Playgroud) Lombok在自动生成构造函数时错过了field的注释.有没有办法在构造函数输入参数中保留字段的注释?
生成构造函数的类,
@RequiredArgsConstructor(onConstructor = @__(@Inject))
public class Test {
@Named("MyField")
private final String field;
@Named("MyHandler")
private final SomeHandler handler;
}
Run Code Online (Sandbox Code Playgroud)
生成的类:
public class Test {
@Named("MyField")
private final String field;
@Named("MyField")
private final SomeHandler handler;
@Inject
public Test(final String field, final SomeHandler handler) {
this.field = field;
this.handler = handler;
}
}
Run Code Online (Sandbox Code Playgroud)
期望的课程:
public class Test {
@Named("MyField")
private final String field;
@Named("MyHandler")
private final SomeHandler handler;
@Inject
public Test(@Named("MyField")final String field,
@Named("MyHandler")final SomeHandler handler) {
this.field = field;
this.handler …Run Code Online (Sandbox Code Playgroud)