build: 309
updated: Jun 17 2008 Jodd Library
Community
Project Reports
Jodd
Jodd-WOT
|
Petite
*A small rock holds back a great wave. (Homer)
Table of Contents
Petite is an IOC container. Yes, yet another one;) Then again, it is quite simple to use, requires no configuration, it is so small so anyone can understand how it works from the code, doesn't depends on third-parties and... Well, it will always stay this way. Enough said:) Highlights
Basics and manual registration
Lets take two POJO beans: public class Foo { Boo boo; public void foo() { if (boo != null) boo.boo(); System.out.println("foo"); } } public class Boo { public void boo() { System.out.println("boo"); } } Petite container builds bean name from class name. When not specified explicitaly, bean names are created by uncapitalizing the class name. As for any other container, beans must be registered before usage. Petite registration is done in Java - no proprietary or weird XML configuration is required. In this basic example, PetiteContainer petite = new PetiteContainer(); petite.register(Foo.class); // equivalent to: petite.register("foo", Foo.class); petite.register(Boo.class); Now both beans are registered in the container. They can be fetched by their bean name: Foo foo = (Foo) petite.getBean("foo"); foo.foo(); Although registered, beans are still not wired. Let's see how to instruct Petite to wire beans. Wiring beans
By default, Petite injects beans in all annotated fields, where field name is used as a bean reference. So, to wire these two beans together, it is enough to annotate the attribute of Foo: public class Foo { @PetiteInject Boo boo; ... } That is all, beans will be wired when they come out of container. Note that accessors methods ( Auto-registration
Since Petite registration is done in Java, it is easy to extend it to some custom way for registering beans (i.e. reading configuration from XML file). Still, manual registration is usually error prone and hard to maintain. Petite provides another way to register beans: auto-registration. Petite auto-registration tool will scan classes on the classpath (including classes insed jar files) and register all beans that are annotated as Petite bean. Since class scanning of full path (and all jars) may be a long operation, it is possible and easy to fine-tune this process by specifying the scanning path and included/excluded jars and packages (see: FindClass) in order to reduce the amount of scanned classes. During scanning, Petite examine classes in a smart way, so only annotated Petite beans will be actually dynamically loaded and then registered in the container. As said, before running the auto-registration tool, beans must be annotated as Petite beans: @PetiteBean public class Foo { ... @PetiteBean public class Boo { Auto-registration is now simple: PetiteContainer petite = new PetiteContainer(); AutomagicPetiteConfig petiteCfg = new AutomagicPetiteConfig(); petiteCfg.configure(petite); Please note that usage of Wiring constructors
Similarly as for the bean properties, Petite provides beans wiring using constructors. In above example, we can modify the public class Foo { final Boo boo; public Foo(@PetiteInject Boo boo) { this.boo = boo; } ... } Wiring beans using constructors has some limitations. There must be one or none suitable constructors, otherwise, exception is thrown. Suitable constructor is one that has all parameters annotated. Partially annotated constructors are detected and exception is thrown. Interfaces
Until now we have been working only with concrete bean implementations. Let's look at the situation when some beans have more than one bean implementation. Petite also accepts bean's interfaces, when pointer to concrete implementation is defined by template in an annotation value, set on package (or interface itself). Common usage is to set package annotation Let's have the bean interface and its implementation: package jodd.petite.test; public interface Ioo { void hello(); Foo getFoo(); } package jodd.petite.test.impl; public class DefaultIoo implements Ioo { @PetiteInject Foo foo; public void hello() { System.out.println("DefaultIoo.hello"); } public Foo getFoo() { return foo; } } Although it is possible to annotate the interface, this is not consider as a practical approach, since for single implementation change all interfaces have to be manually changed. Therefore, we will use package annotation, defined in @PetiteImpl("impl.Default*") package jodd.petite.test; import jodd.petite.meta.PetiteImpl; When an interface is registered in the Petite container, it will first examine the interface for All wirings are defined in the concrete implementation, not the interface. When using auto-configuration, only interfaces have to be annotated with Auto-wire
Although not preferable, Petite supports auto-wiring of the beans. When turned on for a container, all bean's properties will be considered for wiring. This behavior is equivalent to one when all fields are actually annotated with Single bean may be registered for auto-wiring mode independently from container. Auto-wiring can be turned on/off anytime. Using auto-wiring feature may have some impact on application's performance. Scopes
Petite beans are scoped. The following scopes are implemented:
Users may create custom scopes easily. Create proxies transparently
It is easy to generate bean proxies transparently. Petite has single point of bean registration. Therefore, user may override this method and create proxy over bean type before it is registered in the container. An easy way to create proxy is using Proxetta: public class MyPetiteContainer extends PetiteContainer { protected final Proxetta proxetta; public MyPetiteContainer(Proxetta proxetta) { this.proxetta = proxetta; } @Override protected void registerBean(String name, Class type, Class extends Scope> scopeType, Autowire autowire) { type = proxetta.defineProxy(type); super.registerBean(name, type, scopeType, autowire); } } Misc
Petite detects and disallows circular dependencies. |