天天看點

Spring - JSR-330 标準注解

從Spring 3.0開始,Spring開始支援JSR-330标準的注解(依賴注入)。這些注解和Spring注解掃描的方式是一直的,開發者隻需要在classpath中配置相關的jar包即可。

如果開發者使用Maven來管理項目的話,​

​javax.inject​

​​artifact在Maven倉庫中是可用的(​​http://repo1.maven.org/maven2/javax/inject/javax.inject/1/​​)。開發者隻需要在pom中引用這個依賴即可。

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

通過@Inject和@Named進行依賴注入

JSR-330中,@javax.inject.Inject和Spring中的@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。比如如下的例子。

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

public class SimpleMovieLister {

    private Provider<MovieFinder> movieFinder;

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

如果開發者希望來通過名字來限定注入的Bean,可以使用@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;
    }

    // ...
}      

@Named等同于@Component注解

JSR-330中,@javax.inject.Named和Spring中的@Component的職責類似。

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

@Named("movieListener")
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注解的時候,也同樣可以使用元件掃描。

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

和Spring的@Component元件不同的是,JSR-330的Named注解不可以組合來使用,如果希望自定義元件注解的話,還請使用Spring的元件注解。

JSR-330标準注解的限制

當使用JSR-330标準的注解時,了解其和Spring注解的不同點也是十分必要的,參考如下表。

Spring javax.inject.* javax.inject 限制
@Autowired @Inject

​@Inject​

​​注解沒有​

​required​

​​屬性,但是可以通過Java 8的​

​Optional​

​取代
@Component @Named JSR_330标準并沒有提供複合的模型,隻有一種方式來識别元件
@Scope(“singleton”) @Singleton JSR-330預設的作用域類似Spring的​

​prototype​

​​,然而,為何和Spring的預設保持一緻,JSR-330标準中的Bean在Spring中預設也是單例的。如果要使用非單例的作用域,開發者應該使用Spring的​

​@Scope​

​​注解。​

​java.inject​

​​也提供一個​

​@Scope​

​注解,然而,這個注解僅僅可以用來建立自定義的作用域時才能使用。
@Qualifier @Qualifier/@Named

​javax.inject.Qualifier​

​​僅僅是一個元注解,用來建構自定義限定符的。而String的限定符(比如Spring中的​

​@Qualifier​

​​)可以通過​

​javax.inject.Named​

​來實作
@Value - 不等價
@Required - 不等價
@Lazy - 不等價
ObjectFactory