Open doggie1989 opened 10 years ago
Unfortunately I'm pretty sure the registration interface is unavoidable based on how GWT works today. The problem is that GWT doesn't support reflection, since the information that would be required isn't included in the compiled javascript. GWT's alternative is to use compile-time code generation via GWT.create, but the only information that can be passed to GWT.create is a single class literal. So if we want to be able to register different sets of handlers for each class (which is pretty unavoidable), we have to define a unique interface for each class so that the code generator can tell what it's supposed to generate. UiBinder and EventBinder both have the same problem.
Ray Cromwell of the GWT team posted a proposal several years ago on ways to relax this constraint and pass additional information to GWT.create, but I don't think there has been any work towards implementing it: http://timepedia.blogspot.com/2009/03/relaxing-constraints-on-gwtcreate.html. I might try bugging the GWT team about that again at some point or take a look at implementing it myself, but until then I'm pretty sure this is the best we can do.
Note that there's one small thing you can do if you're using Gin - if you inject the registration object into your class, it will be GWT.create'd automatically so you don't have to call GWT.create. I've updated the readme to show how to do this.
Thanks for your reply.
Currently,such as gwt Editor ,UiBinder, we cannot avoid writing lots of inner Interfaces in the class...
Hi Will gwt 3.0 allow us to pass additional information to GWT.create ? any Google inner information? Regards
I'm not aware of anything - @gkdn might know if there are any plans along these lines.
Not on our radar right now...
Ahh, xapi does exactly that ("extend" GWT.create...). I actually added the ability to define your own magic methods so you can pass class literals, string/primitive literals, enums and opaque objects into an ast-driven generator. That is how I implemented literal-based reflection; SomeClass.class.getMethod("literalName", LiteralType.class) works by making .getMethod a magic method, which can then examine the instance object (SomeClass.class), and the arguments (JStringLiteral, JArrayType filled with JClassLiterals), to then invoke a generator and replace the JMethodCall with a different generated method.
For reference-based reflection, I have to enhance the class object by embedding runtime maps of methods, fields, constructors and annotations. If the method calls do not have all literals (cannot map back to class literal), then it goes into runtime-reference mode, where the class must be enhanced or else it will fail then. It can get fairly bloated, even with annotations to limit total retention, but it does work. However, I would always recommend pursuing use of compile-time reflection (using a TypeOracle) instead of runtime reflection, as you will get better performance doing so at compile-time.
In this case, I would actually recommend something like an apt annotation processor to generate a factory which does switch(bean.getClass().getName()) { case "all.types.referenced.in.App": }. Of course, this would pull in extra code that you may not need, so it's really up to you... But that is far better than enhancing all possible beans to include all possible methods and annotations... that would get real expensive, real fast.
Or probably the best option, if you use @Configuration
objects to declare a bunch of @Bean
annotated methods, just make a generator which can run on that config object, inspect all methods annotated with Bean, then inspect all those for types for methods annotated with @Subscribe
. BeanEnhancer<when-type-assignable class="com.foo.BeanEnhancer" />
to define your generator.
we need to do
interface MyRegistration extends EventRegistration {}
andeventBus.register(this, (MyRegistration) GWT.create(MyRegistration.class));
before using the @Subscribe. That is boilerplate code like in gwteventbinder the Event need to extend GenericEvent.I am also using guava EventBus with Spring in server side which let spring auto register
import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe;
import java.lang.annotation.Annotation; import java.lang.reflect.Method;
import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component;
@Component public class EventBusPostProcessor implements BeanPostProcessor {
}
Do you know any approach to do this ? for example, with GIN ?
Thank you very much~!