Java:学习@Autowired

原贴收藏在IT老兵驿站

前言

使用 Spring 框架,不可避免要接触到注解,会遇到 @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 autowiringvarious ways to wire in beansmaking beans optional, resolving bean conflicts using @Qualifier annotation along with potential exception scenarios.

Spring 从 2.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 AnnotationConfigApplicationContext to 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: <context:annotation-config/>

想使用注解,先需要配置 Spring 可以支持注解,有两种方式,一个是在代码中,像上文这样,使用 AnnotationConfigApplicationContext ;一个是在 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.

注解可以直接放在属性上,这样就不需要再使用 getter 和 setter 了,上面的例子讲了如何用在属性上,注入了一个 fooFormatter 的对象

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 FooFormatter when FooService is 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;

    }

}

也可以用在 setter 方法上,还是基于前面的例子,这次放在了 setter 方法上,当 FooService 被创建时,setter 方法会被调用,伴随着一个 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] found for dependency:

expected at least 1 bean which qualifies as autowire candidate for this dependency.

Dependency annotations:

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

To avoid this from happening, a bean can optionally 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 FooFormatter implements Formatter {

    public String format() {

        return "foo";

    }

}

1

2

3

4

5

6

7

@Component("barFormatter")

public class BarFormatter implements 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 NoUniqueBeanDefinitionException exception 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 found 2: 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 @Qualifier with 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 @Qualifier annotation matches with the name declared in the @Component annotation 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 @Qualifier annotation 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 FooFormatter implements Formatter {

    public String format() {

        return "foo";

    }

}

1

2

3

4

5

6

7

8

@FormatterType("Bar")

@Component

public class BarFormatter implements 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.

总结

老外的文章讲的真清楚,他们会对读者负责,很认真地、很细致地把所有问题讲清楚,由浅入深,非常容易理解。

参考

https://www.baeldung.com/spring-autowire

java - Can you use @Autowired with static fields? - Stack Overflow 介绍了静态域能不能自动装配

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值