Spring
Tuesday, August 6, 2013
Tuesday, March 20, 2012
@AutoWiring
1. Introduction:
In the last blog I have explained the
Dependency Injection. DI helps in injecting the dependencies using either the
<property> or <constructor-arg> elements .And hence whenever there
is a new bean defined one needs to go and change the spring configuration file
(servlet xml). Just to avoid this, spring offers AutoWiring. AutoWiring helps
in reducing configuration overhead by not using the property and constructor
arg elements. How?
Let’s first understand the AutoWiring.
Bookish
Definition:
The Spring container is able to autowire
relationships between collaborating beans. This means that it is possible to
automatically let Spring resolve collaborators (other beans) for your bean by
inspecting the contents of the BeanFactory.
Simple Definition:
Autowiring let spring container decide which bean to inject into a controller.
It helps in avoiding the explicit wiring of bean properties.
It helps in avoiding the explicit wiring of bean properties.
Example: To display the
results from Database, A controller needs a DataSource bean.
Now in Dependency
Injection what we do is, we inject the datasoure bean to the controller by
setter or constructor
dependency injection in the xml configuration file. Autowiring lets Spring to
decide how to wire dependency and hence we do not need to explicitly wire bean
properties.
2. Types of AutoWiring:
- byName: Based on the name of a property.
- byType: Based on a type of class on a setter.
- constructors: Based on a constructor argument's class types.
- autodetect : Chooses constructor or byType through introspection of the bean class.
Code examples:
Class
1:
package
com.sk.autowiring;
public class Player {
private Game game;
public
void setGame(Game game) {
this.game = game;
}
//Some logic...
}
Class2:
package
com.sk.autowiring;
public class Game {
private String gameName;
// Some logic ..
}
Class3:
package
com.sk.autowiring;
public class Batsman {
private String batsmanType;
//...
}
2.1 ByName:
Autowiring
by property name. This option will inspect the container and look for a bean
named exactly the same as the property which needs to be autowired. This uses
the setter method.
In Dependency Injection, we have done
explicit wiring for beans. For ex.
<bean id="player"
class="com.sk.autowiring.Player" >
<property
name="game" ref="game" />
</bean>
<bean id="game"
class="com.sk.autowiring.Game" >
<property
name="gameName" value="cricket" />
</bean>
But using autowiring , there is no
need to declare the property tag . As long as the “game” bean has same name as
the property of “player” bean, which is “game”, spring will wire it
automatically.
<bean id="player"
class="com.sk.autowiring.Player" autowire="byName"/>
<bean id="game"
class="com.sk.autowiring.Game" >
<property
name="gameName" value="cricket" />
</bean>
2.2 ByType :
When attempting to autowire a property
by type, Spring will look for beans whose type is assignable to the property’s
type.
<bean
id="player" class="com.sk.autowiring.Player" >
<property
name="batsman" ref="batsman" />
</bean>
<bean
id="batsman" class="com.sk.autowiring.Batsman" >
<property
name="batsmanType" value="opening" />
</bean>
With autowire by type, properties need
not to be set. Spring will find the same data type and wire it automatically.
<bean
id="player" class="com.sk.autowiring.Player"
autowire="byType" />
<bean
id="batsman" class="com.sk.autowiring.Batsman" >
<property
name="batsmanType" value="opening" />
</bean>
There can be a lot of beans which are
of the same type and hence in that case spring will throw exception. There are
2 options using which We can avoid
a)
primary attribute : Bean element’s primary
attribute helps in identifying a primary
candidate for autowiring. If its value is true, then that particular bean will
be chosen in favor of others.
<bean
id="batsman" class="com.sk.autowiring.Batsman” primary=”false”/>
b)
autowire-candidate attribute : Bean elements’s
is used to identify a preferred autowire candidate among al of them. This
attribute actually eliminates beans from considerations of autowiring when the
value is set to false.
<bean
id="batsman" class="com.sk.autowiring.Batsman” autowire-candidate=”false”/>
2.3 constructor:
Based on a constructor argument's
class types .If the bean is configured using constructor injection, we do not
need to define <constructor-arg> elements and let Spring automatically choose constructor elements
from beans in the spring context.
When bean property is
wired explicitly:
<bean id="player"
class="com.sk.autowiring.Player" >
<constructor-arg>
<ref bean="batsman" />
</constructor-arg>
</bean>
<bean id="batsman"
class="com.sk.autowiring.Batsman" >
<property name="batsmanType"
value="openning" />
</bean>
With autowire by type,
constructor arg elements need not to be set.Spring will find the same data type
and wire it automatically.
<bean id="player"
class="com.sk.autowiring.Player" autowire="constructor"
/>
<bean id="batsman" class="com.sk.autowiring.Batsman"
>
<property name="batsmanType"
value="openning" />
</bean>
2.4 autodetect:
In Spring, "Autowiring by
AutoDetect", means chooses "autowire by constructor". If default
constructor (argument with any data type), otherwise uses "autowire by type".
<bean
id="player" class="com.sk.autowiring.player"
autowire="autodetect" />
<bean id="game"
class="com.sk.autowiring.Game" />
3. Autowiring of beans with @Autowired annotations
Autowiring of beans with @Autowired
annotations feature started from Spring 2.5 version. @Autowired annotation can be used to auto wire bean on the setter
method, constructor or a field. Spring checks the property on which this is
being defined and then it will try to perform ‘byType’ autowiring on that
property. You don’t need a setter method to use it. Since Annotation wiring is not turned on by
default and hence we need to enable it.
3.1 Enable autowiring:
<context:annotation-config />
In the Spring’s context configuration namespace (servlet.xml)
<beans xmlns="http://www.springframework.org/schema/beans"
.....................
<context:annotation-config />
</beans>
3.2 @Autowired property Examples:
1. @Autowired setter method
package
com.sk.autowiring;
import
org.springframework.beans.factory.annotation.Autowired;
public
class Player {
private Game game;
//Autowiring
setter
@Autowired
public void setGame(Game game) {
this.game = game;
}
}
2. @Autowired construtor
package
com.sk.autowiring;
import org.springframework.beans.factory.annotation.Autowired;
public
class Player {
private
Game game;
// Autowiring
Constructor
@Autowired
public Player(Game game) {
this.game = game;
}
}
3. @Autowired field
package
com.sk.autowiring;
import
org.springframework.beans.factory.annotation.Autowired;
public
class Player {
//Autowiring field
@Autowired
private Game game;
}
4. @Qualifier
There can be a case when more than one
bean is defined of the same name or type. In that event, there is no way for
@Autowired to choose which one should really be selected. To help @Autowired
figure out which bean you want, you can accompany it with Spring's @Qualifier
annotation. The @Qualifier annotation used to control which bean should be autowire
on a field.
For example,
bean configuration file with two similar game beans.
<beans
xmlns="http://www.springframework.org/schema/beans"
.............
<context:annotation-config />
<bean id="Player"
class="com.sk.autowiring.Player">
<property
name="name" value="Sushant" />
</bean>
<bean id="Game1"
class="com.sk.autowiring.Game">
<property
name="gameName" value="Cricket" />
</bean>
<bean
id="Game2" class="com.sk.autowiring.Game">
<property
name="gameName" value="Football" />
</bean>
</beans>
Now how will
Spring decide which bean it should wire? To fix it, you can use @Qualifier to
auto wire a particular bean, for example,
package com.sk.autowiring;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.beans.factory.annotation.Qualifier;
public
class Player {
@Autowired
@Qualifier("Game1")
private Game game;
}
In this
case, Game1 is autowired.This is how
the Autowiring works.
5. Pros\Cons of Autowiring
As there are pros and
cons of each approach, with this also there are few. Defining everything explicitly
in the xml obviously is easier to understand by everybody and even to new
people who joins the team at a later stage. But then maintaining an xml file
for each and everything will be a big overhead. Annotations are easier to use
and maintain.
Now even Spring
autowiring also increases the complexity for the servlet xml file and hence
better to use the @Autowired annotations.
So which ever approach will be used all are at
last Dependency Injection only.
Sunday, March 4, 2012
Dependency Injection
1) Dependency Injection:
Spring framework has the capability to inject the dependencies to java objects. DI is also known as Inversion of Control (IOC). I have just learnt the Dependency Injection in spring. Although there are lots of articles on this topic but my intention is to let people who are starting to learn spring framework, understand the concepts of DI.
Bookish Definition: Dependency Injection is the dependencies of java objects managed by a container so that Object can concentrate on its functionality rather than for its dependencies. When applying DI, objects are given their dependencies at the creation time by some external entity that coordinates each object in the system. In other words, dependencies are injected into objects.
Simple definition: DI can be simply told as decoupling of work (encouraging the loose coupling).The only thing we need to understand is an object's dependencies should be on interfaces and not on "concrete" objects, when possible. (A concrete object is any object created with the keyword
new
.) Hence we cannot use new keyword.
Work: Display the names of Indian states.
Class A: Handles the logic part.
Class B: Handles query part from DB.
Class C: Interface
Now Class A does not bother how Class B got the results whether it got it by doing simple query or by writing stored procedures or PL\SQL, what it needs is query results. It will take that results through the interface (Class C) and display the names of the Indian states.
This is somewhat similar to the Hollywood Principle: "Don't call us, we'll call you”. i.e. You implement the interfaces, you get registered. You get called when the time is right.
I don’t want you to confuse further as it’s easy to understand the topic with the help of an example.
Code example:
In the below example, what we are going to do is to find it out which Object Relational Mapping we are using in the code. We will create an Interface, one main class, two different Orm techniques class and then a service class. We will inject the ORM through the controller bean xml and displayOrm method which will display the Orm tool being used.
<pre class="brush: js">
<div id="tweets">
<pre class="brush: js">
<div id="tweets">
Orm.java
----------------
package com.sk;
public interface Orm {
public String getOrmName();
}
</div>
</pre>
</pre>
The IBatis and Hibernate class implements Orm interface and getOrmName method.
<pre class="brush: js">
<div id="tweets">
IBatis.java
----------------
package com.sk;
public class IBatis implements Orm {
@Override
public String getOrmName() {
return "I'm using iBatis";
}
}
Hibernate.java
-------------------
package com.sk;
public class Hibernate implements Orm {
@Override
public String getOrmName() {
return "I'm using Hibernate";
}
}
</div>
</pre>
We have a OrmService class that tells the developer which Object Relational mapping is being used. The OrmService class holds reference to the Orm.
<pre class="brush: js">
<div id="tweets">
<pre class="brush: js">
<div id="tweets">
OrmService.java
---------------------
package com.sk;
public class OrmService {
private Orm orm = new Hibernate();
public void displayOrm(){
System.out.println(orm.getOrmName());
}
}
</div>
</pre>
</pre>
At last we will create OrmTool class which will display the Object Relational mapping is being used.
<pre class="brush: js">
<div id="tweets">
<pre class="brush: js">
<div id="tweets">
OrmTool.java
-------------------
package com.sk;
public class OrmTool {
public static void main(String[] args) {
OrmService ormService = new OrmService();
ormService.displayOrm();
}
}
</div>
</pre>
</div>
</pre>
As you can see it is pretty simple, here we create an instance of the OrmService class and call the displayOrm() method. This method will display the ORM being used.
Let's have a look at the class diagram of this example. The green arrows indicate generalization and the blue arrow indicates association.
|
As you can see this architecture is tightly coupled. We create an instance of the Orm in the OrmService class in the following way to display Hibernate.
<pre class="brush: js">
<div id="tweets">
private Orm orm = new Hibernate();
</div>
</pre>
</pre>
To make our Orm display iBatis we need to make modifications to the OrmService class like this.
<pre class="brush: js">
<div id="tweets">
<pre class="brush: js">
<div id="tweets">
private Orm orm = new IBatis();
</div>
</pre>
</pre>
So it is tightly coupled. Now let’s see how we can avoid this by using the Dependency Injection design pattern. The spring framework provides powerful container to manage the components. The container will inject the required dependencies. We can inject the dependencies using the setter or constructor injection (this is explained in the later section).
Here we will see how we can do this using the setter injection.
<pre class="brush: js">
<div id="tweets">
<pre class="brush: js">
<div id="tweets">
OrmService.java
---------------------
package com.sk;
public class OrmService {
Orm orm;
public void setOrm(Orm orm) {
this.orm = orm;
}
public void displayOrm(){
System.out.println(orm.getOrmName());
}
}
</div>
</pre>
The value for the Orm will be set using the setOrm() method. The Orm object is never instantiated in the OrmService class, but still we access it. Usually this will throw a NullPointerException, but here the containers will instantiate the object for us, so it works fine.
After making all the changes, the class diagram of the example look like this.
|
The container comes into picture and it helps in injecting the dependencies. The bean configuration is done in the Controller-beans.xml file.
<pre class="brush: js">
<div id="tweets">
<pre class="brush: js">
<div id="tweets">
Controller-beans.xml
-------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring- beans.xsd">
<bean id="hibernate" class="com.sk.Hibernate"></bean>
<bean id="iBatis" class="com.sk.IBatis"></bean>
<bean id="ormService" class="com.sk.OrmService">
<property name="orm">
<ref local="hibernate"/>
</property>
</bean>
</beans>
</div>
</pre>
</div>
</pre>
We define each bean using the bean tag. The id attribute of the bean tag gives a logical name to the bean and the class attribute represents the actual bean class. The property tag is used to refer the property of the bean. To inject a bean using the setter injection you need to use the ref tag.
Here a reference of Hibernate is injected to the Orm bean. Now when we want to change the ORM to IBatis, the only change we need to do is, to change the bean reference in the ref tag.
<pre class="brush: js">
<div id="tweets">
<pre class="brush: js">
<div id="tweets">
<bean id="ormService" class="com.sk.OrmService">
<property name="orm">
<ref local="iBatis"/>
</property>
</bean>
</div>
</pre>
</div>
</pre>
2) Types of DI
2.1 Constructor Injection
2.2 Setter Injection
2.1 Constructor Injection :
Constructor-based DI is affected by invoking a constructor with a number of arguments, each representing a dependency.
<pre class="brush: js">
<div id="tweets">
<pre class="brush: js">
<div id="tweets">
a) Through XML
<bean id="ormService" class="com.sk.OrmService">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean
b) Through Java config :
public class OrmService {
// the OrmService has a dependency on a Orm
private Orm orm;
// a constructor so that the Spring container can 'inject' a Orm
public OrmService (Orm orm) {
this. orm = orm;
}
// business logic that actually 'uses' the injected Orm is omitted...
}
</div>
</pre>
2.2 Setter Injection
Setter-based DI is realized by calling setter methods on your beans after invoking a no-argument constructor or no-argument static factory method to instantiate your bean.
<pre class="brush: js">
<div id="tweets">
<pre class="brush: js">
<div id="tweets">
a) Through XML :
<bean id="ormService" class="com.sk.OrmService">
<property name="name" value="sk"/>
</bean>
b) Through Java config
public class OrmService {
// the OrmService has a dependency on the Orm
private Orm orm;
// a setter method so that the Spring container can 'inject' a Orm
public void setOrm(Orm orm) {
this.orm = orm;
}
// business logic that actually 'uses' the injected Orm is omitted...
}
</div>
</pre>
</div>
</pre>
3. XML or Java Configuration
The wiring up of the dependencies with the objects can be done using Java code and XML both. Some people prefer java code and some prefer xml configuration. I think it is a simpler to work with Java code. But then for beginners and business people, xml is better as it is easily configurable. This thought is divided and may be in some other article I will try to cover it.
Subscribe to:
Posts (Atom)