Lightweight dependency injection framework for Java 8 and above that eliminates factories and the use of 'new' through @Inject annotation
—
AOP interceptors, method matching, private modules, and other advanced dependency injection patterns.
Classes for matching methods and types for AOP interception.
/**
* Returns true or false for a given input. Used for method and type matching.
* @param <T> Type being matched
*/
public interface Matcher<T> {
/**
* Returns true if this matcher matches the given input.
* @param t Input to match
* @return true if matches
*/
boolean matches(T t);
/**
* Returns a matcher that matches if both this and other match.
* @param other Other matcher
* @return Combined matcher using AND logic
*/
default Matcher<T> and(Matcher<? super T> other);
/**
* Returns a matcher that matches if either this or other matches.
* @param other Other matcher
* @return Combined matcher using OR logic
*/
default Matcher<T> or(Matcher<? super T> other);
}
/**
* Factory for common matcher implementations.
*/
public final class Matchers {
/**
* Matches any input.
* @return Matcher that matches everything
*/
public static Matcher<Object> any();
/**
* Matches subclasses of the given type.
* @param superclass Superclass to match
* @return Matcher for subclasses
*/
public static Matcher<Class> subclassesOf(Class<?> superclass);
/**
* Matches elements annotated with the given annotation.
* @param annotationType Annotation type
* @return Matcher for annotated elements
*/
public static Matcher<AnnotatedElement> annotatedWith(Class<? extends Annotation> annotationType);
/**
* Matches classes in the given package.
* @param targetPackage Package to match
* @return Matcher for classes in package
*/
public static Matcher<Class> inPackage(Package targetPackage);
}Modules that create private child injectors with selective exposure.
/**
* A private module can expose a subset of its bindings. The bindings not exposed
* are not available to the outside world, but the private module can still
* inject its non-exposed bindings internally.
*/
public abstract class PrivateModule implements Module {
/**
* Creates bindings and other configuration for this module.
*/
protected abstract void configure();
/**
* Exposes the binding for the given type.
* @param type Type to expose
*/
protected final void expose(Class<?> type);
/**
* Exposes the binding for the given key.
* @param key Key to expose
*/
protected final void expose(Key<?> key);
/**
* Returns the private binder for this module.
* @return Private binder instance
*/
protected final PrivateBinder binder();
}Usage Examples:
// AOP interception
public class LoggingModule extends AbstractModule {
@Override
protected void configure() {
// Intercept all methods in Service classes annotated with @Timed
bindInterceptor(
Matchers.subclassesOf(Service.class),
Matchers.annotatedWith(Timed.class),
new TimingInterceptor()
);
}
}
// Private module
public class DatabasePrivateModule extends PrivateModule {
@Override
protected void configure() {
// Internal bindings - not visible outside
bind(ConnectionPool.class).to(HikariConnectionPool.class);
bind(QueryExecutor.class).to(PreparedStatementExecutor.class);
// Public interface - exposed to outside world
bind(DatabaseService.class).to(DatabaseServiceImpl.class);
expose(DatabaseService.class);
}
}Install with Tessl CLI
npx tessl i tessl/maven-com-google-inject--guice