guice で @PostConstruct

@PostConstruct , @PreDestroy などの JSR-250 Lifecycle annotation は、
これらを使ってちゃんと実装すべきなのだろうけど、
guice/extensions/jsr250 at master · mathieucarbou/guice · GitHub
@PostConstruct だけ、簡単につかいたい。

結構、古い断片のコードだけど参考になるものを見つけた
https://gist.github.com/diversit/04dc5da5f76d51a23f91eaab81806386
ここを参考に、以下、Guice の bindListner を書く。

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.function.Consumer;
import java.util.function.Predicate;
import javax.annotation.PostConstruct;
import com.google.inject.TypeLiteral;
import com.google.inject.spi.InjectionListener;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;
/**
 * PostConstructTypeListener
 */
public class PostConstructTypeListener implements TypeListener{
    private final Predicate<Method> filterPostConstructMethods = m -> {
        PostConstruct annotation = m.getAnnotation(PostConstruct.class);
        return annotation != null;
    };
    @Override
    public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter){
        encounter.register(new InjectionListener<I>() {
            @Override
            public void afterInjection(final I injectee) {
                invokePostConstructMethodsOn(injectee);
            }
        });
    }
    private <T> void invokePostConstructMethodsOn(T instance){
        Arrays.asList(instance.getClass().getMethods())
        .stream()
        .filter(filterPostConstructMethods)
        .forEach(invokeMethodOnInstance(instance));
    }
    private final <T> Consumer<Method> invokeMethodOnInstance(T instance){
        return method->{
            try{
                method.invoke(instance);
            }catch(Exception e){
                throw new RuntimeException(String.format("@PostConstruct error: %s", e.getMessage()), e);
            }
        };
    }
}

guice の Module configure で記述するのは、以下のとおり。

     binder().bindListener(Matchers.any(), new PostConstructTypeListener());

@PostConstruct を付与するメソッドは public で、引数無しでなくてはならない。
という制約はあるものの、コンストラクタの次に自動的に実行されるようになる。

public Sample{
     public Sample(){
     }
     @PostConstruct 
     public void init(){
           // コンストラクタ実行後に実行される。
     }

@PostConstruct を使うには、Maven pom.xml で以下の記述も必要だ

    <dependency>
       <groupId>javax.annotation</groupId>
       <artifactId>javax.annotation-api</artifactId>
       <version>1.3.2</version>
    </dependency>