您的位置:首页 > 编程语言 > Java开发

spring in action Third 5

2012-08-28 14:14 357 查看
看到第三章了,越来越有趣了,第三章讲述spring是如何简化xml文件冗余繁琐的配置,从而更加简洁和方便的使用spring,和大家一起学习。

Minimizing XML configuration in Spring

Fortunately, Spring offers a few tricks to help cut down on the amount of XML configuration required:
¡ 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.
¡ 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.

3.1 Automatically wiring bean properties
Taking advantage of such obvious wirings, Spring offers autowiring. Rather than explicitly wiring bean properties, why not let Spring sort out those cases when there’s no question about which bean reference
should be wired?
3.1.1 The four kinds of autowiring
When it comes to automatically wiring beans with their dependencies, Spring has a lot of clues to work from. As a result, Spring provides four flavors of 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.

¡ autodetect--Attempts to apply
constructor autowiring first. If that fails,
byType will be tried.

AUTOWIRING BY NAME
<bean id="kenny2" class="com.springinaction.springidol.Instrumentalist"> <property name="song" value="Jingle Bells" /> <property name="instrument" ref="saxophone" /> </bean>
<bean id="instrument" class="com.springinaction.springidol.Saxophone" />
<bean id="kenny" class="com.springinaction.springidol.Instrumentalist"
autowire="byName"> <property name="song" value="Jingle Bells" /> </bean>

AUTOWIRING BY TYPE
Autowiring using byType works in a similar way to byName, except that instead of con- sidering 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.
But there’s a limitation to 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.

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.
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.
For example, to establish that the saxophone bean isn’t the primary choice when autowiring Instruments:
<bean id="saxophone" class="com.springinaction.springidol.Saxophone"
primary="false"/>

<bean id="saxophone" class="com.springinaction.springidol.Saxophone" autowire-candidate="false" />

AUTOWIRING CONSTRUCTORS
<bean id="duke" class="com.springinaction.springidol.PoeticJuggler"
autowire="constructor" />
Autowiring by constructor shares the same limitations as
byType.

BEST-FIT AUTOWIRING
<bean id="duke" class="com.springinaction.springidol.PoeticJuggler" autowire="autodetect"/>
When a bean has been configured to autowire by
autodetect, Spring will attempt to autowire by
constructor first. If a suitable constructor-to-bean match can’t be found, then Spring will attempt to autowire by type.
3.1.2 Default autowiring
<?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-3.0.xsd default-autowire="byType">
</beans>
Note that I said that default-autowire would be applied to all beans in a given Spring configuration file; I didn’t say that it would be applied to all beans in a Spring application context. You could have multiple
configuration files that define a single application context, each with their own default autowiring setting.

Also, just because you’ve defined a default autowiring scheme, that doesn’t mean that you’re stuck with it for all of your beans. You can still override the default on a bean-by-bean basis using the autowire
attribute.
3.1.3 Mixing auto with explicit wiring
Just because you choose to autowire a bean, that doesn’t mean you can’t explicitly wire some properties. You can still use the <property> element on any property just as if you hadn’t set autowire.
<bean id="kenny" class="com.springinaction.springidol.Instrumentalist" autowire="byType"> <property name="song" value="Jingle Bells" /> <property name="instrument" ref="saxophone" /> </bean>
As illustrated here, mixing automatic and explicit wiring is also a great way to deal with ambiguous autowiring that might occur when autowiring using byType.
<bean id="kenny" class="com.springinaction.springidol.Instrumentalist" autowire="byType"> <property name="song" value="Jingle Bells" /> <property name="instrument"><null/></property> </bean>
One final note on mixed wiring: when using constructor autowiring, you must let Spring wire all of the constructor arguments—you can’t mix
<constructor-arg> ele-ments with constructor autowiring.

3.2 Wiring with annotations
The simplest way to do that is with the <context:annotation-config> element from Spring’s context configuration namespace:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:annotation-config />

<!-- bean declarations go here -->
</beans>
Spring 3 supports a few different annotations for autowiring:

¡ Spring’s own @Autowired annotation

¡ The @Inject annotation from JSR-330
¡ The @Resource annotation from JSR-250
3.2.1 Using @Autowired
@Autowired
public void setInstrument(Instrument instrument) {

this.instrument = instrument; }
When Spring sees that you’ve annotated setInstrument() with @Autowired it’ll try to perform
byType autowiring on the method.
What’s especially interesting about @Autowired is that you don’t have to use it with a setter method. You can use it on any method to automatically wire in bean references:

@Autowired
public voidheresYourInstrument(Instrumentinstrument){

this.instrument=instrument; }
The @Autowired annotation can even be used on constructors:
@Autowired
public Instrumentalist(Instrumentinstrument){

this.instrument=instrument; }

@Autowired
private Instrument instrument;

If there are no applicable beans or if multiple beans could be autowired, then
@Autowired will run into some trouble.
Fortunately, there’s a way that we can help @Autowired out in those circumstances.
OPTIONAL AUTOWIRING
But it’s also possible that the property being wired is truly optional and a null value is acceptable. In that case, you can configure optional autowiring by setting @Autowired’s required attribute to false.
For example:
@Autowired(required=false)
private Instrumentinstrument;
Here, Spring will try to wire the instrument property. But if no bean of type Instrument can be found, then no problem. The property will be left null.
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 anno- tated with
@Autowired, Spring will choose the constructor which has the most argu- ments that can be satisfied.

QUALIFYING AMBIGUOUS DEPENDENCIES
To help @Autowired figure out which bean you want, you can accompany it with Spring’s @Qualifier annotation.
@Qualifier to specify a bean named
guitar:
@Autowired @
Qualifier("guitar")
private Instrumentinstrument;
As shown here, the
@Qualifier annotation will try to wire in a bean whose ID matches
guitar.
In addition to narrowing by a bean’s ID, it’s also possible to narrow by a qualifier that’s applied to a bean itself. For example, suppose that the guitar bean were declared in XML as follows:
<bean class="com.springinaction.springidol.Guitar"> <qualifier value="stringed" /> </bean>
Here the <qualifier> element qualifies the guitar bean as a stringed instrument. But instead of specifying the qualifier in XML, you could have also annotated the Guitar class itself with the @Qualifier annotation:
@Qualifier("stringed") public classGuitarimplementsInstrument{ ... }

CREATING CUSTOM QUALIFIERS

@StringedInstrument
public class Guitar implements Instrument { ... }

@Autowired
@StringedInstrument
private Instrument instrument;

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. As long as only one bean is annotated
with @StringedInstrument, it’ll be wired into the instrument property.
Spring’s
@Autowired annotation is one way to cut down on the amount of Spring configuration
XML. But it does create a Spring-specific dependency within the classes that use it (even if that dependency is just an annotation). Fortunately, Spring also supports a standard Java alternative
to @Autowired. Let’s look at how to use
@Inject from the Dependency Injection for Java specification.

3.2.2 Applying standards-based autowiring with @Inject
The centerpiece of
JSR-330 is the
@Inject annotation. This annotation is an almost complete drop-in replacement for Spring’s
@Autowired annotation.

@Inject
private Instrumentinstrument;

Just like @Autowired,
@Inject can be used to autowire properties, methods, and con- structors. Unlike
@Autowired, @Inject
doesn’t have a
required
attribute.
Therefore,
@Inject-annotated dependencies are expected to be fulfilled, failing with an excep- tion if they’re not.
JSR-330 has another trick up its sleeve in addition to the @Inject annotation. 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 refer- ences and injection of multiple instances of a bean.
private Set<Knife> knives;
@Inject
public KnifeJuggler(Provider<Knife> knifeProvider) {

knives = new HashSet<Knife>(); for (int i = 0; i < 5; i++) { knives.add(knifeProvider.get()); } }
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. In this case, the get() method is called five times. And since the Knife bean is a prototype, we know that the Set of knives will be given five distinct Knife objects to work it.
QUALIFYING @INJECTED PROPERTIES
@Inject
@Named("guitar")

private Instrument instrument;

The key difference between Spring’s @Qualifier and JSR-330’s @Named is one of semantics. Whereas @Qualifier helps narrow the selection of matching beans (using the bean’s ID by default), @Named specifically
identifies a selected bean by its ID.

CREATING CUSTOM JSR-330 QUALIFIERS

As you can see, the only real difference between listing 3.2 and 3.1 is the import state- ment for the @Qualifier annotation. In listing 3.1 we used the one from the org.springframework.beans.factory.annotation
package. But this time, we’re using the standards-friendly @Qualifier from the javax.inject package. Otherwise, they’re virtually the same.
3.2.3 Using expressions with annotation injection
@Value("Eruption")
private String song;
As it turns out, simple values aren’t where
@Value shines. Instead,
@Value finds its power with
SpEL
expressions. Recall that SpEL
lets you dynamically evaluate complex expressions, at runtime, into values to be wired into bean properties. That makes
@Value a powerful wiring option.

@Value("#{systemProperties.myFavoriteSong}") private String song;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: