Tuesday, April 24, 2007

Spring Injecting dependencies

The basic principle behind Dependency Injection (DI) is that objects define their dependencies (that is to say the other objects they work with) only through constructor arguments, arguments to a factory method, or properties which are set on the object instance after it has been constructed or returned from a factory method. Then, it is the job of the container to actually inject those dependencies when it creates the bean. This is fundamentally the inverse, hence the name Inversion of Control (IoC), of the bean itself being in control of instantiating or locating its dependencies on its own using direct construction of classes, or something like the Service Locator pattern.

It becomes evident upon usage that code gets much cleaner when the DI principle is applied, and reaching a higher grade of decoupling is much easier when beans do not look up their dependencies, but are provided with them (and additionally do not even know where the dependencies are located and of what actual class they are).

The BeanFactory supports both of these variants for injecting dependencies into beans it manages. (It in fact also supports injecting setter-based dependencies after some dependencies have already been supplied via the constructor approach.)

Bean dependency resolution generally happens as follows:

1.

The BeanFactory is created and initialized with a configuration which describes all the beans. (Most Spring users use a BeanFactory or ApplicationContext implementation that supports XML format configuration files.)
2.

Each bean has dependencies expressed in the form of properties, constructor arguments, or arguments to the static-factory method when that is used instead of a normal constructor. These dependencies will be provided to the bean, when the bean is actually created.
3.

Each property or constructor argument is either an actual definition of the value to set, or a reference to another bean in the container.
4.

Each property or constructor argument which is a value must be able to be converted from whatever format it was specified in, to the actual type of that property or constructor argument. By default Spring can convert a value supplied in string format to all built-in types, such as int, long, String, boolean, etc.


The Spring container validates the configuration of each bean as the container is created, including the validation that properties which are bean references are actually referring to valid beans. However, the bean properties themselves are not set until the bean is actually created. For those beans that are singleton-scoped and set to be pre-instantiated (such as singleton beans in an ApplicationContext), creation happens at the time that the container is created, but otherwise this is only when the bean is requested. When a bean actually has to be created, this will potentially cause a graph of other beans to be created, as its dependencies and its dependencies' dependencies (and so on) are created and assigned.

Circular dependencies

If you are using predominantly constructor injection it is possible to write and configure your classes and beans such that an unresolvable circular dependency scenario is created.

Consider the scenario where you have class A, which requires an instance of class B to be provided via constructor injection, and class B, which requires an instance of class A to be provided via constructor injection. If you configure beans for classes A and B to be injected into each other, the Spring IoC container will detect this circular reference at runtime, and throw a BeanCurrentlyInCreationException.

One possible solution to this issue is to edit the source code of some of your classes to be configured via setters instead of via constructors. Another solution is not to use constructor injection and stick to setter injection only.

You can generally trust Spring to do the right thing. It will detect mis-configuration issues, such as references to non-existent beans and circular dependencies, at container load-time. It will actually set properties and resolve dependencies as late as possible, which is when the bean is actually created. This means that a Spring container which has loaded correctly can later generate an exception when you request a bean if there is a problem creating that bean or one of its dependencies. This could happen if the bean throws an exception as a result of a missing or invalid property, for example. This potentially delayed visibility of some configuration issues is why ApplicationContext implementations by default pre-instantiate singleton beans. At the cost of some upfront time and memory to create these beans before they are actually needed, you find out about configuration issues when the ApplicationContext is created, not later. If you wish, you can still override this default behavior and set any of these singleton beans to lazy-initialize (that is not be pre-instantiated).

Finally, if it is not immediately apparent, it is worth mentioning that when one or more collaborating beans are being injected into a dependent bean, each collaborating bean is totally configured prior to being passed (via one of the DI flavors) to the dependent bean. This means that if bean A has a dependency on bean B, the Spring IoC container will totally configure bean B prior to invoking the setter method on bean A; you can read 'totally configure' to mean that the bean will be instantiated (if not a pre-instantiated singleton), all of its dependencies will be set, and the relevant lifecycle methods (such as a configured init method or the IntializingBean callback method) will all be invoked.

ref

Wednesday, April 18, 2007

Wildcards v.s. Generic Methods

Wildcards

void printCollection(Collection c) {
for (Object e : c) {
System.out.println(e);
} // ok

Collection c = new ArrayList ();
c.add(new Object()); //compile time error

Since we don’t know what the element type of c stands for, we cannot add objects
to it.

interface Collection {

public boolean containsAll(Collection c);
public boolean addAll(Collection c);
}

We could have used generic methods here instead:

interface Collection {
public boolean containsAll(Collection c);
public boolean addAll(Collection c);
// hey, type variables can have bounds too!
}

In both containsAll and addAll, the type parameter T is used only once. The return type doesn't depend on the type parameter, nor does any other argument to the method (in this case, there simply is only one argument). This tells us that the type argument is being used for polymorphism; its only effect is to allow a variety of actual argument types to be used at different invocation sites. If that is the case, one should use wildcards. Wildcards are designed to support flexible subtyping, which is what we're trying to express here.

Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type. If there isn't such a dependency. A generic method should not be used.

Use both generic methods and wildcards in tandem.

Class Collections {
public static void copy(List dest, list src) {...}
}



Saturday, April 14, 2007

Generics in Java

Generics are about abstraction. Generics let you create classes and methods that work in the same way on different types of objects.

Array types in Java have an inheritance relationship that allows this kind of aliasing to occur:

Date [ ] dates = new Date[10];
Object [ ] objects = dates;
objects[0] = "not a date"; // Runtime ArrayStoreException;


However, arrays have runtime representations as different classes and they check themselves at runtime, throwing an ArrayStoreException in just this case. So, in theory, Java code is not guaranteed typesafe by the compiler if you use arrays in this way.

Why Isn't a List a List<object>"?

The reason gets back to the heart of the rationale for generics that we discussed in the introduction: changing APIs. In the simplest case, supposing an ObjectList type extends a DateList type, the DateList would have all of the methods of ObjectList and we could still insert Objects into it. Now, you might object that generics let us change the APIs, so that doesn't apply anymore. That's true, but there is a bigger problem. If we could assign our DateList to an ObjectList variable, we would have to be able to use Object methods to insert elements of types other than Date into it. We could alias the DateList as an ObjectList and try to trick it into accepting some other type:
    DateList dateList = new DateList( );
ObjectList objectList = dateList;
objectList.add( new Foo( ) ); // should be runtime error!

Thursday, April 12, 2007

Java Constructor Chain

The way how java constructors are chained has three parts and is applied repeatedly for each successive constructor that is invoked:

  • If the first statement of a constructor is an ordinary statement—i.e., not a call to this( ) or super( )—Java inserts an implicit call to super( ) to invoke the default constructor of the superclass. Upon returning from that call, Java initializes the instance variables of the current class and proceeds to execute the statements of the current constructor.

  • If the first statement of a constructor is a call to a superclass constructor via super( ), Java invokes the selected superclass constructor. Upon its return, Java initializes the current class's instance variables and proceeds with the statements of the current constructor.

  • If the first statement of a constructor is a call to an overloaded constructor via this( ), Java invokes the selected constructor, and upon its return, simply proceeds with the statements of the current constructor. The call to the superclass's constructor has happened within the overloaded constructor, either explicitly or implicitly, so the initialization of instance variables has already occurred.

Tuesday, April 10, 2007

Java ClassLoaders

Class loader delegation model is the graph of class loaders that pass loading requests to each other. The bootstrap class loader is at the root of this graph. Class loaders are created with a single delegation parent and looks for a class in the following places:
  • Cache
  • Parent
  • Self
Three standard class loaders:
  • bootstrap class loader (jre/lib)
  • extension class loader (jre/lib/ext)
  • system class loader (CLASSPATH)
Three phases of class loading
  • loading: locating the required class file
by searching through the respective classpaths and loading in the bytecode. Within the JVM, the loading process gives a very basic memory structure to the class object. Methods, fields, and other referenced classes are not dealt with at this stage. As a result, the class is not usable.

  • Linking is the most complicated of the three phases. It can be broken down into three main stages:
  • Bytecode verification. The class loader does a number of checks on the bytecodes of the class to ensure that it is well formed and well behaved.
  • Class preparation. This stage prepares the necessary data structures that represent fields, methods, and implemented interfaces that are defined within each class.
  • Resolving. In this stage, the class loader loads all the other classes referenced by a particular class. The classes can be referenced in a number of ways:
    - Superclasses
    - Interfaces
    - Fields
    - Method signatures
    - Local variables used in methods
  • initializing phase
Any static initializers contained within a class are executed. At the end of this phase, static fields are initialized to their default values.

At the end of these three phases, a class is fully loaded and is ready for use. Note that class loading can be performed in a lazy manner and therefore some parts of the class loading process may be done on first use of the class rather than at load time.

Explicit and Implicit loading

Explicit:
cl.loadClass() (cl instance of java.lang.ClassLoader)
Class.forName()

Articles
Part 1
Part 2
Part 3
Part 4

Thursday, April 5, 2007

Mac Short Key

Mac OS X offers a glorious assortment of predefined keystrokes for jumping to the most important locations on your Mac: your Home folder, the Applications folder, the Utilities folder, the Computer window, your iDisk, the Network window, and so on.

Better yet, the keystrokes are incredibly simple to memorize: Just press Shift- and the first letter of the location you want. Shift--H opens your Home folder, Shift--A opens the Applications folder, and so on. You learn one, you've learned 'em all.

The point here is that Shift-, in Tiger, means places.

The other system-wide key combo, Option-, means functions. For example, Option--D hides or shows the Dock, Option--H is the Hide Others command, Option--+ magnifies the screen (if you've turned on this feature), Option--Esc brings up the Force Quit dialog box, and so on. Consistency is always nice.