autowired java_Java:学习@Autowired

原贴收藏在IT老兵驿站。

前言

使用SpringMVC,现在不可避免要接触注解,会遇到@Autowired,查询了google,找到这篇文章,摘录下来,做一些笔记。为什么这样呢?因为至少来说,以当前的理解,自己来写,不太可能超越这篇文章,我也不想像很多人那样搞所谓“二次原创”,其实不还是抄袭,只是针对了判定抄袭的规则来做文章,不耍这样的小聪明,没有意义。

本篇选取主要的部分翻译一下,具体的过程可以参考代码,本文的英文难度不高,可以尝试着读一读。

正文

1. Overview

Starting with Spring 2.5, the framework introduced a new style of Dependency Injection driven by @Autowired Annotations. This annotation allows Spring to resolve and inject collaborating beans into your bean.

In this tutorial, we will look at how to enable autowiring,variousways to wire in beans,making beans optional, resolving bean conflicts using @Qualifier annotation along with potential exception scenarios.

Spring2.5之后,可以使用@Autowired 注解来实现DI(依赖注入),这个词本身的英文意思就是自动装配。

2. Enabling @Autowired Annotations

If you are using Java based configuration in your application you can enable annotation-driven injection by using AnnotationConfigApplicationContextto load your spring configuration as below:

1

2

3

@Configuration

@ComponentScan("com.baeldung.autowire.sample")

public class AppConfig {}

As an alternative, in Spring XML, it can be enabled by declaring it in Spring XML files like so: 

想使用注解,现需要配置Spring可以支持注解,有两种方式,一个是在代码中,一个是在XML中,这个涉及到另外一些知识点,作者这里是假设读者是知道这些的,不明白的话,需要去查一查。

3. Using @Autowired

Once annotation injection is enabled, autowiring can be used on properties, setters, and constructors.

可以用在属性、setter方法和构造器上。

3.1. @Autowired on Properties

The annotation can be used directly on properties, therefore eliminating the need for getters and setters:

1

2

3

4

5

6

7

@Component("fooFormatter")

public class FooFormatter {

public String format() {

return "foo";

}

}1

2

3

4

5

6

7

@Component

public class FooService {

@Autowired

private FooFormatter fooFormatter;

}

In the above example, Spring looks for and injects fooFormatter when FooService is created.

如何用在属性上。

3.2. @Autowired on Setters

The@Autowired annotation can be used on setter methods. In the below example, when the annotation is used on the setter method, the setter method is called with the instance of FooFormatterwhen FooServiceis created:

1

2

3

4

5

6

7

8

9

public class FooService {

private FooFormatter fooFormatter;

@Autowired

public void setFooFormatter(FooFormatter fooFormatter) {

this.fooFormatter = fooFormatter;

}

}

如何用在方法上。

3.3. @Autowired on Constructors

The@Autowired annotation can also be used on constructors. In the below example, when the annotation is used on a constructor, an instance of FooFormatter is injected as an argument to the constructor when FooService is created:

1

2

3

4

5

6

7

8

9

public class FooService {

private FooFormatter fooFormatter;

@Autowired

public FooService(FooFormatter fooFormatter) {

this.fooFormatter = fooFormatter;

}

}

如何用在构造器方法上。

4. @Autowired and Optional Dependencies

Spring expects @Autowired dependencies to be available when the dependent bean is being constructed. If the framework cannot resolve a bean for wiring, it will throw the below-quoted exception and prevent the Spring container from launching successfully:

1

2

3

4

5

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:

No qualifying bean of type [com.autowire.sample.FooDAO] foundfor dependency:

expected at least1 bean which qualifies as autowire candidatefor this dependency.

Dependency annotations:

{@org.springframework.beans.factory.annotation.Autowired(required=true)}

To avoid this from happening, a bean can optional be specified as below:

1

2

3

4

5

6

public class FooService {

@Autowired(required =false)

private FooDAO dataAccessor;

}

如果没有找到响应的bean,又不想系统停止加载,参考上面的写法。

5. Autowire Disambiguation

By default, Spring resolves @Autowired entries by type. If more than one beans of the same type are available in the container, the framework will throw a fatal exception indicating that more than one bean is available for autowiring.

@Autowired是根据类型来进行装备的。但是会存在同一类型内有多个备选bean,这个时候,框架会抛出一个致命错误----这种问题倒是暂时还没有遇到过,下面讲述了三种解决方案。

5.1. Autowiring by @Qualifier

The @Qualifier annotation can be used to hint at and narrow down the required bean:

1

2

3

4

5

6

7

@Component("fooFormatter")

public class FooFormatterimplements Formatter {

public String format() {

return "foo";

}

}1

2

3

4

5

6

7

@Component("barFormatter")

public class BarFormatterimplements Formatter {

public String format() {

return "bar";

}

}1

2

3

4

5

6

public class FooService {

@Autowired

private Formatter formatter;

}

Since there are two concrete implementations of Formatter available for the Spring container to inject, Spring will throw a NoUniqueBeanDefinitionExceptionexception when constructing the FooService:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException:

No qualifying bean of type [com.autowire.sample.Formatter] is defined:

expected single matching bean but found2: barFormatter,fooFormatter

This can be avoided by narrowing the implementation using a @Qualifier annotation:

1

2

3

4

5

6

7

public class FooService {

@Autowired

@Qualifier("fooFormatter")

private Formatter formatter;

}

By specifying the @Qualifierwith the name of the specific implementation, in this case as fooFormatter, we can avoid ambiguity when Spring finds multiple beans of the same type.

Please note that the value of the @Qualifierannotation matches with the name declared in the @Componentannotation of our FooFormatter implementation.

使用@Qualifier注解来标识谁是合格的。

5.2. Autowiring by Custom Qualifier

Spring allows us to create our own @Qualifier annotation. To create a custom Qualifier, define an annotation and provide the @Qualifierannotation within the definition as below:

1

2

3

4

5

6

7

8

9

@Qualifier

@Target({

ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})

@Retention(RetentionPolicy.RUNTIME)

public @interface FormatterType {

String value();

}

Once defined, the FormatterType can be used within various implementations to specify custom value:

1

2

3

4

5

6

7

8

@FormatterType("Foo")

@Component

public class FooFormatterimplements Formatter {

public String format() {

return "foo";

}

}1

2

3

4

5

6

7

8

@FormatterType("Bar")

@Component

public class BarFormatterimplements Formatter {

public String format() {

return "bar";

}

}

Once the implementations are annotated, the custom Qualifier annotation can be used as below:

1

2

3

4

5

6

7

8

@Component

public class FooService {

@Autowired

@FormatterType("Foo")

private Formatter formatter;

}

The value specified in the @Target annotation restrict where the qualifier can be used to mark injection points.

In the above code snippet, the qualifier can be used to disambiguate the point where Spring can inject the bean into a field, a method, a type, and a parameter.

5.3. Autowiring by Name

As a fallback Spring uses the bean name as a default qualifier value.

So by defining the bean property name, in this case as fooFormatter, Spring matches that to the FooFormatter implementation and injects that specific implementation when FooService is constructed:

1

2

3

4

5

6

public class FooService {

@Autowired

private Formatter fooFormatter;

}

使用名字来自动装配。

6. Conclusion

Although both @Qualifier and bean name fallback match can be used to narrow down to a specific bean, autowiring is really all about injection by type and this is how best to use this container feature.

The source code of this tutorial can be found in the GitHub project – this is an Eclipse based project, so it should be easy to import and run as it is.

总结

老外的文章讲的真清楚,他们会对读者负责,很认真地把所有问题讲清楚,不像很多国人,哪怕是很多好像挺有名的教授出的书,都是“言简意赅”,看着好费劲,给人一种高高在上的感觉。当年读清华严蔚敏出的《数据结构》,读着就非常费劲,后来看大师出的《算法导论》,反而容易理解,中国人怎么总就是这么高傲呢。

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值