Pre-requisite trails
Spring Constructor Injection
Spring Auto-Wire: By Type
Concept Overview
Typically in Spring, dependency injection is achieved using
bean
,
constructor-arg
and
property
tags.
However, in large applications, the number of beans will increase and the corresponding XML written to configure the numerous beans will become very large and unwieldly.
Spring provides a feature called ‘Auto-Wiring’ that minimizes the XML to be written provided that certain assumptions are made about the nomenclature of beans and properties. Using ‘Auto-Wiring’ feature, the number of tags like
constructor-arg
and
property
is significantly minimized and the size of XML is reduced considerably for large applications.
Spring provides four kinds of Auto-Wirings:
- Auto-Wire by Name using byName attribute
- Auto-Wire by Type using byType attribute
- Auto-Wire by Constructor for Constructor Injection using constructor attribute
- Auto-Wire by Auto Detect using autodetect attribute
In this trail, we shall focus on the item (3) from the above list i.e. Auto-Wiring by Constructor using
constructor
attribute. The rule followed by Spring to resolve dependencies for Auto-Wiring by Constructor:
- Spring attempts to match all constructor arguments of the autowired bean with beans that have the same type
- Properties for which there is no matching bean will remain unwired
Usually, auto-wiring using constructor is helpful only if we don’t have multiple beans of same type. In practice, this is a severe restriction as our application could have multiple types assignable to the same constructor argument.
A downside of using auto-wiring constructors is that if there are multiple beans with the same type then Spring will throw an exception as it cannot decide which bean to auto-wire. In such cases, we should use the
primary=”false”
bean tag for all the beans that are not intended to be the primary choice for Spring for auto-wiring by constructor and use
primary=”true”
bean tag for the bean that Spring should consider as the primary candidate for auto-wiring by constructor.
If a class has multiple constructors, any of which can be satisfied by autowiring, then Spring will throw an exception as it cannot decide which bean to auto-wire.
Also, if we want to eliminate a bean from participating in auto-wiring process itself, then we can set
autowire-candidate=”false”
in the bean tag.
Note that in practice, auto-wiring by constructor is not a preferred way of auto-wiring for application development.
Sample Program Overview
The sample program is based on an ATM system which contains a Printer that prints the balance information for an account.
We will create the Printer class .
We will then create the ATM with member as printer resolving this dependency using constructor injection.
We will also create the spring-config.xml and declare the Printer and ATM beans.
We will then use Spring’s auto-wire by constructor feature to inject Printer into ATM bean.
Finally, we will test our setup using TestAutoWireConstructor class which will load Spring context and get a reference to ATM class. We will print the balance information for an account number to verify that dependency injection using auto-wiring by constructor has occured successfully.
- commons-logging.jar
- log4j.jar
- org.springframework.aop.jar
- org.springframework.asm.jar
- org.springframework.beans.jar
- org.springframework.context.jar
- org.springframework.context.support.jar
- org.springframework.core.jar
- org.springframework.expression.jar
Create the Printer class(see sample code below).
Create the printBalanceInformation() method (see line 5 below)
Create the ATM class(see sample code below).
Create a member printer (see line 5 below)
Create constructor which accepts Printer as argument (see lines 8-11 below)
Create getter method for printer (see lines 13-15 below).
Create the printBalanceInformation() method (see line 17 below) and delegate the call to Printer.printBalanceInformation() method (see line 18 below).
Create the spring-config.xml file (see below).
Declare bean for Printer (see lines 10-12 below)
Declare bean for ATM (see line 14 below)
Auto-Wire by constructor using
autowire=”constructor”
attribute in bean tag (see line 15 below) which demonstrates the usage of Spring Auto-Wiring by constructor feature.
Note that we did not declare the
constructor-arg
tag with
bean
tag of ATM thereby reducing the XML size.
Finally, we need a java program to test the our setup.This is done by TestAutoWireConstructor (see source code below).
We need to tell Spring framework to use the ‘spring-config.xml’ to load our beans (see line 11 below).
We get the reference to ATM class through Spring using the bean name ‘atm’ (see line 12 below).
We access the atm.printBalanceInformation(() method and print the balance information to verify that auto-wiring constructor has occured successfully (see line 14 below).
This sample program has been packaged as a jar installer which will copy the source code (along with all necessary dependencies) on your machine and automatically run the program for you as shown in the steps below. To run the sample program, you only need Java Runtime Environment (JRE) on your machine and nothing else.
(Alternatively you can go the folder containing the springautowireconstructor-installer.jar and execute the jar using
java -jar springautowireconstructor-installer.jar
command)
This source code for this program is downloaded in the folder specified by you (say, C:\Temp) as an eclipse project called
springautowireconstructor
. All the required libraries have also been downloaded and placed in the same location. You can open this project from Eclipe IDE and directly browse the source code. See below for details of the project structure.