package ru.vyarus.guice.ext; import com.google.inject.AbstractModule; import com.google.inject.matcher.Matcher; import com.google.inject.matcher.Matchers; import ru.vyarus.guice.ext.core.field.AnnotatedFieldTypeListener; import ru.vyarus.guice.ext.core.method.AnnotatedMethodTypeListener; import ru.vyarus.guice.ext.core.type.GeneralTypeListener; import ru.vyarus.guice.ext.core.util.ObjectPackageMatcher; import ru.vyarus.guice.ext.log.Log; import ru.vyarus.guice.ext.log.Slf4jLogAnnotationProcessor; import ru.vyarus.guice.ext.managed.DestroyableTypeProcessor; import ru.vyarus.guice.ext.managed.PostConstructAnnotationProcessor; import ru.vyarus.guice.ext.managed.PreDestroyAnnotationProcessor; import ru.vyarus.guice.ext.managed.destroyable.Destroyable; import ru.vyarus.guice.ext.managed.destroyable.DestroyableManager; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; /** * Additional annotations support module: @PostConstruct, @PreDestroy, @Log. * * @author Vyacheslav Rusakov * @since 29.06.2014 */ @SuppressWarnings("checkstyle:ClassDataAbstractionCoupling") public class ExtAnnotationsModule extends AbstractModule { private Matcher<Object> typeMatcher; /** * Default module constructor to check annotations on all beans. */ public ExtAnnotationsModule() { this(Matchers.any()); } /** * Constructs annotation module with annotation scan limited to provided package. * (used mainly for startup performance optimization) * * @param pkg package to limit beans, where annotations processed */ public ExtAnnotationsModule(final String pkg) { this(new ObjectPackageMatcher<Object>(pkg)); } /** * Constructs annotation module with custom bean matcher for annotations processing. * * @param typeMatcher matcher to select beans for annotations processing */ public ExtAnnotationsModule(final Matcher<Object> typeMatcher) { this.typeMatcher = typeMatcher; } @Override protected void configure() { final DestroyableManager manager = configureManager(new DestroyableManager()); bindListener(typeMatcher, new GeneralTypeListener<Destroyable>( Destroyable.class, new DestroyableTypeProcessor(manager))); bindListener(typeMatcher, new AnnotatedMethodTypeListener<PostConstruct>( PostConstruct.class, new PostConstructAnnotationProcessor())); bindListener(typeMatcher, new AnnotatedMethodTypeListener<PreDestroy>( PreDestroy.class, new PreDestroyAnnotationProcessor(manager))); bindListener(typeMatcher, new AnnotatedFieldTypeListener<Log>( Log.class, new Slf4jLogAnnotationProcessor())); } /** * Registers destroyable manager in injector and adds shutdown hook to process destroy on jvm shutdown. * * @param manager destroyable manager instance * @return manager instance */ protected DestroyableManager configureManager(final DestroyableManager manager) { bind(DestroyableManager.class).toInstance(manager); // if logic will not call destroy at least it will be called before jvm shutdown Runtime.getRuntime().addShutdownHook(new Thread(manager)); return manager; } }