Tuesday, April 24, 2007
Spring Injecting dependencies
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
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
public
// 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
}
Saturday, April 14, 2007
Generics in Java
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
- Cache
- Parent
- Self
- bootstrap class loader (jre/lib)
- extension class loader (jre/lib/ext)
- system class loader (CLASSPATH)
- loading: locating the required class file
- 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
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
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.