Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 46

Automatic wiring

Automatic bean wiring


• Declaring beans using the <bean> element and inject
<bean> with values using either the <constructor-arg> or
<property> element is fine for a small application where
you only have a handful of beans.
• But as your application grows, so will the amount of XML
configuration you’ll write.
• Autowiring helps reduce or even eliminate the need for
<property> and <constructor-arg> elements by letting
Spring automatically figure out how to wire bean
dependencies.
Automatic bean wiring
• Autodiscovery takes autowiring a step further by letting
Spring figure out which classes should be configured as
Spring beans, reducing the need for the <bean> element
• When used together, autowiring and autodiscovery can
dramatically reduce the amount of XML Spring
configuration.
• Often you’ll need only a handful of lines of XML,
regardless of how many beans are in your Spring
application context
Automatic bean wiring
• What is logic behind autowiring?
• If I were to say “The moon is bright tonight,” it’s not likely
that you’d respond by asking “Which moon?”
• That’s because we all reside on the Earth and in that
context it’s obvious that we are talking about Luna, the
Earth’s moon
• If I were to say the same thing while we were standing
on Jupiter, you’d be justified in asking which of the
planet’s 63 natural satellites I had in mind.
• But on Earth, there’s no ambiguity
Automatic bean wiring
• When it comes to wiring bean properties, it’s sometimes
quite obvious which bean reference should be wired into
a given property.
• If your application context only has one bean of type
javax.sql.DataSource, then any bean that needs a
DataSource will certainly need precisely that DataSource
• Taking advantage of such obvious wirings, Spring offers
autowiring
Automatic bean wiring
• There are several ways for autowiring:
– byname - Attempts to match all properties of the autowired bean
with beans that have the same name (or ID) as the properties.
Properties for which there’s no matching bean will remain
unwired.
– byType - Attempts to match all properties of the autowired bean
with beans whose types are assignable to the properties.
Properties for which there’s no matching bean will remain
unwired.
– constructor—Tries to match up a constructor of the autowired
bean with beans whose types are assignable to the constructor
arguments
Autowiring by Name
• In Spring, everything is given a name.
• Thus bean properties are given names, as are the beans
that are wired into those properties.
• Suppose that the name of a property happens to match
the name of the bean that’s to be wired into that property.
• That happy coincidence could serve as a hint to Spring
that the bean should be automatically wired into the
property
Autowiring by Name
• Let us observe kenny bean

• We have explicitly configured Kenny’s instrument


property using <property>
• Assume now that we have declared the Saxophone as a
<bean> with an id of instrument:
Autowiring by Name
• If this is the case, the id of the Saxophone bean would be
the same as the name of the instrument property.
• Spring can take advantage of this to automatically configure
Kenny’s instrument by setting the autowire property

• byName autowiring establishes a convention where a


property will automatically be wired with a bean of the same
name
Autowiring by Name
• If there’s a bean in the context whose id is instrument,
it’ll be autowired into the instrument property

• The downside of using byName autowiring is that it


assumes that you’ll have a bean whose name is the
same as the name of the property of another bean.
Autowiring by Type
• Autowiring using byType works in a similar way to
byName, except that instead of considering a property’s
name, the property’s type is examined
• When attempting to autowire a property by type, Spring
will look for beans whose type is assignable to the
property’s type.
• For example, suppose that the kenny bean’s autowire
property is set to byType instead of byName.
• The container will search itself for a bean whose type is
Instrument and wire that bean into the instrument
property
Autowiring by Type
• The saxophone bean will be automatically wired into
Kenny’s instrument property because both the
instrument property and the saxophone bean are of type
Instrument.
Autowiring by Type
• What happens if Spring finds more than one bean whose
type is assignable to the autowired property?
• In such a case, Spring isn’t going to guess which bean to
autowire and will instead throw an exception.
• Consequently, you’re allowed to have only one bean
configured that matches the autowired property.
• For example, there are likely to be several beans whose
types are subclasses of Instrument.
Autowiring by Type
• To overcome ambiguities with autowiring by type, Spring
offers two options: you can either identify a primary
candidate for autowiring or you can eliminate beans from
autowiring candidacy.
• To identify a primary autowire candidate, you’ll work with
the <bean> element’s primary attribute.
• If only one autowire candidate has the primary attribute
set to true, then that bean will be chosen in favor of the
other candidates.
Autowiring by Type
• But here’s the weird side of the primary attribute: it
defaults to true.
• That means that all autowire candidates will be primary
(and thus none will be preferred).
• So, to use primary, you’ll need to set it to false for all of
the beans that are not the primary choice
Autowiring by Type
• The primary attribute is only useful for identifying a
preferred autowire candidate.
• If you’d rather eliminate some beans from consideration
when autowiring, then you can set their autowire-
candidate attribute to false
Autowiring Constructors
• If your bean is configured using constructor injection, you
may choose to put away the <constructor-arg> elements
and let Spring automatically choose constructor
arguments from beans in the Spring context

• This tells Spring to look at PoeticJuggler’s constructors


and try to find beans in the Spring configuration to satisfy
the arguments of one of the constructors.
Autowiring Constructors
• Autowiring by constructor shares the same limitations as
byType.
• Spring won’t attempt to guess which bean to autowire
when it finds multiple beans that match a constructor’s
arguments
• If a class has multiple constructors, any of which can be
satisfied by autowiring, Spring won’t attempt to guess
which constructor to use.
Default autowiring
• If you find yourself putting the same autowire attribute on
every bean in your application context (or even most of
them), you can simplify things by asking Spring to apply
the same autowiring style to all beans that it creates.
• All you need to do is add a default-autowire attribute to
the root <beans> element
Default autowiring
• By default, default-autowire is set to none, indicating that
no beans should be autowired unless they’re individually
configured for autowiring with the autowire attribute
• You can still override the default on a bean-by-bean
basis using the autowire attribute.
Wiring with annotations
• Since Spring 2.5, one of the most interesting ways of
wiring beans in Spring has been to use annotations to
automatically wire bean properties
• Autowiring with annotations isn’t much different than
using the autowire attribute in XML
• It does allow for more fine-grained autowiring, where you
can selectively annotate certain properties for autowiring.
• It is not turned on by default, you must enable it in Spring
configuration with the <context:annotation-config>
element
Wiring with annotations
Wiring with annotations
• Suppose that you want to use @Autowired to have Spring
autowire the instrument property of the Instrumentalist bean.
• You could annotate the setInstrument() method like this:

• Now you can get rid of the <property> element that wires the
Instrumentalist with an instrument.
• When Spring sees that you’ve annotated setInstrument() with
@Autowired it’ll try to perform byType autowiring on the
method.
Wiring with annotations
• You don’t have to use it with a setter method. You can
use it on any method to automatically wire in bean
references:

• The @Autowired annotation can even be used on


constructors
Wiring with annotations
• You can directly annotate properties and do away with
the setter methods altogether (even if the field is private):

• Limitation?
• There must be exactly one bean that’s applicable for wir-
ing into the @Autowired property or parameter.
• If there are no applicable beans or if multiple beans
could be autowired, then @Autowired will run into some
trouble
Wiring with annotations
• If no bean can be wired into the @Autowired-annotated
property or argument, then autowiring fails (with a nasty
NoSuchBeanDefinitionException)
• That may be what you want—to have Spring fail early
when autowiring goes bad rather than later with a
NullPointerException
• it’s also possible that the property being wired is truly
optional and a null value is acceptable.
Wiring with annotations
• Note that the required attribute can be used anywhere
@Autowired can be used.
• But when used with constructors, only one constructor
can be annotated with @Autowired and required set to
true.
• All other @Autowired-annotated constructors must have
required set to false.
• Moreover, when multiple constructors are annotated with
@Autowired, Spring will choose the constructor which
has the most arguments that can be satisfied.
Wiring with annotations
• Problem can also arise if there is more than one bean,
each of which is equally qualified to be wired into a
property or a parameter
• For example, suppose you have two beans that
implement Instrument.
• In that event, there’s no way for @Autowired to choose
which one you really want.
• So, instead of guessing, a
NoSuchBeanDefinitionException will be thrown and
wiring will fail.
Wiring with annotations
• To help @Autowired figure out which bean you want, you
can accompany it with Spring’s @Qualifier annotation.
• For example, to ensure that Spring selects a guitar for
the eddie bean to play, even if there are other beans that
could be wired into the instrument property, you can use
@Qualifier to specify a bean named guitar

• the @Qualifier annotation will try to wire in a bean whose


ID matches guitar.
Wiring with annotations
• It is possible to create custom qualifier annotation
Wiring with annotations
• We can use it instead @Qualifier as follows:

• We can then qualify the @AutowiredInstrument property:

• When Spring tries to autowire the instrument property, it’ll


narrow the selection of all Instrument beans down to just
those that are annotated with @StringedInstrument
Wiring with annotations
• As long as only one bean is annotated with
@StringedInstrument, it’ll be wired into the instrument
property.
• If there’s more than one @StringedInstrument-annotated
bean, then you’ll need to provide further qualification to
narrow it down.
Wiring with annotations
• Java Community Process published the Dependency
Injection for Java specification.
• Known in the Java Community Process as JSR-330 or
more commonly as at inject, this specification brings a
common dependency injection model to Java.
• As of Spring 3, Spring supports the at inject model
• @Inject annotation.
• This annotation is an almost complete drop-in
replacement for Spring’s @Autowired annotation.
Wiring with annotations
• So, instead of using the Spring-specific @Autowired
annotation, you might choose to use @Inject on the
instrument property:

• Just like @Autowired, @Inject can be used to autowire


properties, methods, and constructors.
• Unlike @Autowired, @Inject doesn’t have a required
attribute.
• Therefore, @Inject-annotated dependencies are expected
to be fulfilled, failing with an exception if they’re not
Wiring with annotations
• Rather than inject a reference directly, you could ask
@Inject to inject a Provider.
• The Provider interface enables, among other things, lazy
injection of bean references and injection of multiple
instances of a bean.
• For example, let’s say you have a KnifeJuggler class that
needs to be injected with one or more instances of Knife.
• Let us assume that the Knife bean is declared as having
prototype scope
Wiring with annotations

• Instead of receiving a Knife instance at construction,


KnifeJuggler will receive a Provider<Knife>.
• At this point, only the provider is injected.
• No actual Knife object will be injected until the get() method
is called on the provider.
Wiring with annotations
• @Inject and @Autowired have a lot in common.
• And like @Autowired, the @Inject annotation is prone to
ambiguous bean definitions.
• @Inject’s answer to the @Qualifier annotation is the @Named
annotation.
• The @Named annotation works similar like Spring’s @Qualifier:

• Difference - @Qualifier narrows the selection, @Named


specifically identifies selected bean by ID
Wiring with annotations
• JSR-330 has its own @Qualifier annotation in the
javax.inject package
• JSR-330 version isn’t intended to be used on its own.
• Instead, you’re expected to use it to create custom
qualifier annotations, much as we did with Spring’s
@Qualifier

• The only difference is the import statement for the


@Qualifier annotation
Wiring with annotations
Wiring with annotations
• It is possible to wire simpler values
• @Value, a wiring annotation that lets you wire primitive
values such as int, boolean, and String using annotations.
• To use it, annotate a property, method, or method
parameter with @Value and pass in a String expression to
be wired into the property

• The String parameter passed into @Value is just an


expression—it can evaluate down to any type and thus
Value can be applied to just about any kind of property.
Automatic bean discovery
• When you added <context:annotation-config> to your
Spring configuration, you told Spring that you wanted it
to honor a certain set of annotations in the beans that
you declared and to use those beans to guide bean
wiring
• Even though <context:annotation-config> can go a long
way toward eliminating most uses of <property> and
<constructor-arg> elements from your Spring
configuration, you still must explicitly declare beans
using <bean>
Automatic bean discovery
• The <context:component-scan> element does everything
that <context:annotation-config> does, plus it configures
Spring to automatically discover beans and declare them
for you.
• What this means is that most (or all) of the beans in your
Spring application can be declared and wired without
using <bean>.
• To configure Spring for autodiscovery, use
<context:component-scan> instead of
<context:annotation-config>
Automatic bean discovery
• The <context:component-scan> element works by
scanning a package and all of its subpackages, looking
for classes that could be automatically registered as
beans in the Spring container
• The base-package attribute tells <context:component-
scan> the package to start its scan from.
• So, how does <context:component-scan> know which
classes to register as Spring beans?
Automatic bean discovery
• By default, <context:component-scan> looks for classes
that are annotated with one of a handful of special
stereotype annotations:
– @Component—A general-purpose stereotype annotation
indicating that the class is a Spring component
– @Controller—Indicates that the class defines a Spring MVC
controller
– @Repository—Indicates that the class defines a data repository
– @Service—Indicates that the class defines a service
– Any custom annotation that is itself annotated with @Component
Automatic bean discovery
• Suppose that our application context only has the eddie
and guitar beans in it.
• We can eliminate the explicit <bean> declarations from
the XML configuration by using <context:component-
scan> and annotating the Instrumentalist and Guitar
classes with @Component.
• When Spring scans the package, it’ll find that Guitar is
annotated with @Component and will automatically
register it in Spring.
• By default, the bean’s ID will be generated by camel-
casing the class name
Automatic bean discovery

You might also like