# 1.11 使用JSR 330标准注解

从Spring3.0之后，Spring提供了JSR-330标志注解的支持。这些注解和Spring注解一样被进行扫描，如果想使用它们，需要包含下面的jar包：

> 如果你使用maven，那么javax.inject工件可以在标准maven存储库中使用（[https://repo1.maven.org/maven2/javax/inject/javax.inject/1/）。可以将以下依赖项添加到文件pom.xml中：](https://repo1.maven.org/maven2/javax/inject/javax.inject/1/%EF%BC%89%E3%80%82%E5%8F%AF%E4%BB%A5%E5%B0%86%E4%BB%A5%E4%B8%8B%E4%BE%9D%E8%B5%96%E9%A1%B9%E6%B7%BB%E5%8A%A0%E5%88%B0%E6%96%87%E4%BB%B6pom.xml%E4%B8%AD%EF%BC%9A)

```
<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>
```

## 1.11.1 使用@Inject 和 @Named 注入

你可以使用 @javax.inject.Inject来替代@Autowired：

```
import javax.inject.Inject;

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Inject
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    public void listMovies() {
        this.movieFinder.findMovies(...);
        ...
    }
}
```

与@Autowired一样，你可以在字段级、方法级和构造函数参数级使用@Inject。此外，你可以将注入点声明为Provider，允许通过Provider.get() 调用按需访问较短作用域的bean或延迟访问其他bean。以下示例提供了前面示例的变体：

```
import javax.inject.Inject;
import javax.inject.Provider;

public class SimpleMovieLister {

    private Provider<MovieFinder> movieFinder;

    @Inject
    public void setMovieFinder(Provider<MovieFinder> movieFinder) {
        this.movieFinder = movieFinder;
    }

    public void listMovies() {
        this.movieFinder.get().findMovies(...);
        ...
    }
}
```

如果要对应注入的依赖项使用限定名，则应使用@Named注解，如下例所示：

```
import javax.inject.Inject;
import javax.inject.Named;

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Inject
    public void setMovieFinder(@Named("main") MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...
}
```

与@Autowired一样，@Inject也可以与java.util.Optional或@Nullable一起使用。这在这里更适用，因为@Jnject没有required的属性。以下两个示例演示如何使用@Inject和@Nullable：

```
public class SimpleMovieLister {

    @Inject
    public void setMovieFinder(Optional<MovieFinder> movieFinder) {
        ...
    }
}
```

```
public class SimpleMovieLister {

    @Inject
    public void setMovieFinder(@Nullable MovieFinder movieFinder) {
        ...
    }
}
```

## 1.11.2 @Component的标准等价物@Named 和 @ManagedBean

除了使用@Component，你也可以使用@javax.inject.Named 或者 javax.annotation.ManagedBean，如下：

```
import javax.inject.Inject;
import javax.inject.Named;

@Named("movieListener")  // @ManagedBean("movieListener") could be used as well
public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Inject
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...
}
```

在不指定组件名称的情况下使用@Component是非常常见的。@Named可以以类似的方式使用，如下示例所示：

```
import javax.inject.Inject;
import javax.inject.Named;

@Named
public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Inject
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...
}
```

当你使用@Named或者@ManagedBean，你可以同样使用组件扫描：

```
@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {
    ...
}
```

> 与@Component不同,JSR-330的@Named和JSR-250的@ManagedBean是不可组合的。你应该使用Spring的构造型模型来构建自定义组件注解。

## 1.11.3 JSR-330 标准注解的限制

当使用标准注解时，你应该知道一些重要功能不可用，如下表所示：

| Spring              | javax.inject.\*       | javax.inject限制/描述                                                                                                                                                     |
| ------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| @Autowired          | @Inject               | @Inject没有required属性，可以使用Java8的Optional代替                                                                                                                              |
| @Component          | @Named / @ManagedBean | JSR-330没有提供组合模式，只有一种方式来标记命名组件                                                                                                                                         |
| @Scope("singleton") | @Singleton            | JSR-330默认范围像Spring的prototype，但是为了和Spring的默认值保持一致，在Spring中定义的JSR-330 bean默认是singleton。如果要使用其他的作用范围，那么需要使用Spring的@Scope注解。javax.inject也提供了一个@Scope注解。但是这个注解仅用来创建你自己的注解。 |
| @Qualifier          | @Qualifier / @Named   | javax.inject.Qualifier只是一个用来构建自定义Qualifier的元注解。具体的字符串限定符（如带value的Spring的@Qualifier）可以通过javax.inject.Named关联。                                                          |
| @Value              | -                     | 没有相同功能                                                                                                                                                                |
| @Required           | -                     | 没有相同功能                                                                                                                                                                |
| @Lazy               | -                     | 没有相同功能                                                                                                                                                                |
| ObjectFactory       | Provider              | javax.inject.Provider是Spring的ObjectFactory的直接替代品，它只使用了较短的get（）方法名。它还可以与Spring的@Autowired结合使用，或者与无注解的构造函数和setter方法结合使用。                                                |
