Someone knows some way that how can I achieve the same functionality in Guice as the 'afterPropertiesSet' interface in spring ? ( its a post construction hook )
问题:
回答1:
By far the simplest solution, if you're using constructor injection and not doing anything too crazy, is to create a post-construction method and annotate it with @Inject
:
final class FooImpl implements Foo { private final Bar bar; @Inject FooImpl(Bar bar) { this.bar = bar; ... } @Inject void init() { // Post-construction code goes here! } }
When Guice provides FooImpl, it'll see it has an @Inject
constructor, call it, and then search for methods annotated with @Inject
and call those. The intended use case for this is setter injection, but even if an @Inject
method has no params, Guice will call it.
I don't recommend using this if you're using setter or field injection to inject deps since I don't know if Guice makes any guarantees about the order in which @Inject
methods are called (that is, your init()
method might not be guaranteed to be called last). That said, constructor injection is the preferred approach anyway, so that should be a non-issue.
回答2:
I guess using @PostConstruct is the way to go.
Here is a related blog post : http://macstrac.blogspot.com/2008/10/adding-support-for-postconstruct.html
And here is an addon library that provides the support : http://code.google.com/p/guiceyfruit/
Adding lifecycle support via Guiceyfruit is described here : http://code.google.com/p/guiceyfruit/wiki/Lifecycle
回答3:
It seems it is not yet supported , so for everyone how wants this work , here is small solution.
public class PostConstructListener implements TypeListener{ private static Logger logger = Logger.getLogger(PostConstructListener.class); @Override public <I> void hear(TypeLiteral<I> iTypeLiteral,final TypeEncounter<I> iTypeEncounter) { Class<? super I> type = iTypeLiteral.getRawType(); ReflectionUtils.MethodFilter mf = new ReflectionUtils.MethodFilter() { @Override public boolean matches(Method method) { return method.isAnnotationPresent(PostConstruct.class); } }; ReflectionUtils.MethodCallback mc = new ReflectionUtils.MethodCallback() { @Override public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { if (!(method.getReturnType().equals(Void.TYPE) && method.getParameterTypes().length == 0)) { logger.warn("Only VOID methods having 0 parameters are supported by the PostConstruct annotation!" + "method " + method.getName() + " skipped!"); return; } iTypeEncounter.register(new PostConstructInvoker<I>(method)); } }; ReflectionUtils.doWithMethods(type,mc,mf); } class PostConstructInvoker<I> implements InjectionListener<I>{ private Method method; public PostConstructInvoker(Method method) { this.method = method; } @Override public void afterInjection(I o) { try { method.invoke(o); } catch (Throwable e) { logger.error(e); } } } }
The ReflectionUtils package is defined in spring.
Bind this listener to any event with :
bindListener(Matchers.any(),new PostConstructListener());
in your guice module. Have fun
回答4:
You'll want to read the CustomInjections page on the Guice wiki:
In addition to the standard
@Inject
-driven injections, Guice includes hooks for custom injections. This enables Guice to host other frameworks that have their own injection semantics or annotations. Most developers won't use custom injections directly; but they may see their use in extensions and third-party libraries. Each custom injection requires a type listener, an injection listener, and registration of each.