Tornado Inject - A simple and fast dependency injection system -------------------------------------------------------------- Example: Java-only configuration of beans: public class Beans { @Intercept("txInterceptor") CustomerService customerService() { return new CustomerServiceImpl(); } Interceptor txInterceptor() { return new TransactionInterceptor(); } @Eager CustomerDao customerDao() { return new CustomerDaoImpl(); } } Wire in your beans via Injection: public class CustomerServiceImpl implements CustomerService { @Inject CustomerDao customerDao; public void saveCustomer(String name) { customerDao.saveCustomer(name); } } Start your application: ApplicationContext.registerBeans(new Beans()); CustomerService customerService = ApplicationContext.getBean(CustomerService.class); Description of central concepts: ApplicationContext ------------------ The ApplicationContext houses all your beans. You load it by supplying any object you want to the ApplicationContext#registerBeans() method. The object is called a beanProvider, but does not need to implement any interfaces or even be public. All methods in the beanProvider object is considered beans, and will be instantiated lazily unless you annotate then with @Eager. You don't need to implement an interface, and the methods in the beanProvider can have any visibility you want. The method name is the bean name. Your beans can be automatically injected with other beans from your ApplicationContext if you annotate the fields with the @Inject annotation. Circular dependencies are allowed. You can supply the bean-argument to the @Inject annotation if you want to inject a spesific bean based on name. If you don't, the best matching object based on type and name of the field will be injected. You can even inject beans that are not part of your ApplicationContext via the ApplicationContext.inject(object) method. Any @Inject annotated field will be injected. @Inject ------- Fields in your beans annotated with @Inject will be automatically injected. Circular dependencies are allowed. @Eager ------ beanProviderMethods annotated with @Eager will be created immediately after the ApplicationContext is initialized. Default behavior is to proxy all objects and lazily instantiate them when the first request towards them arrives. @Intercept ---------- Annotate any beanProviderMethod with @Intercept("interceptorBean") to reference another bean that must implement the Interceptor interface. The Interceptor#intercept() method will be called so you can intercept all method calls in the proxied bean and even alter the returned object. This is where you would add automatic transaction handling etc. Interceptor ----------- An interceptor will be called instead of the normal method invocation for proxied beans. A typical scenario for an Interceptor is transaction handling: public Object intercept(Object bean, Method method, Object[] args) throws Exception { startTransaction(); try { method.invoke(bean, args); commitTransaction(); } catch (Exception ex) { // Rethrow InvocationTargetException.targetException(), see comment below rollbackTransaction(); } finally { closeTransaction(); } } The Interceptor, as any other bean, can enjoy dependency injection via the @Inject annotation. It is a good idea to catch InvocationTargetException in your Interceptor and rethrow the TargetException instead to make it clearer where the error occurred when inspecting the stacktrace. InitializingBean ---------------- Let your bean implement this interface to be notified once the ApplicationContext is initialized. Automatic dependency injection for servlets. @WebServlet public class MyServlet extends InjectServlet { @Inject CustomerService } For Tomcat, you can avoid to extend InjectServlet if you add a wrapperClass in META-INF/context.xml: