javax.inject中@Inject、@Named、@Qualifier和@Provider用法

@Inject

    @Inject支持構造函數、方法和字段註解,也可能使用於靜態實例成員。可註解成員可以是任意修飾符(private,package-private,protected,public)。注入順序:構造函數、字段,然後是方法。父類的字段和方法注入優先於子類的字段和方法,同一類中的字段和方法是沒有順序的。

    @Inject註解的構造函數可以是無參或多個參數的構造函數。@Inject每個類中最多註解一個構造函數。

    在字段註解:

  • 用@Inject註解
  • 字段不能是final的
  • 擁有一個合法的名稱

    在方法上註解:

  • 用@Inject註解
  • 不能是抽象方法
  • 不能聲明自身參數類型
  • 可以有返回結果
  • 擁有一個合法的名稱
  • 可以有0個或多個參數

        @Inject MethodModirers ResultType Identifier(FormalParameterList ) Throws MethodBody

    [上述翻譯:inject的doc文檔,翻譯不好敬請諒解]

    構造函數註解:

@Inject
public House(Person owner) {
	System.out.println("---這是房屋構造函數---");
	this.owner = owner;
}
    字段註解:

@Inject private Person owner;
    方法註解:

@Inject
public void setOwner(Person owner) {
	this.owner = owner;
}
    @Inject註解和Spring的@Autoware註解都是根據類型對其進行自動裝配。

    SpringUtil類:

public class SpringUtil {
	private static ApplicationContext context = null;
	public static ApplicationContext getApplicationContext() {
		if (context == null) {
			context = new ClassPathXmlApplicationContext("spring.xml");
		}
		return context;
	}

	public static ApplicationContext getApplicationContext(String path) {
		return new ClassPathXmlApplicationContext(path);
	}

	public static ApplicationContext getAnnotationConfigApplicationContext(String basePackages) {
		return new AnnotationConfigApplicationContext(basePackages);
	}
}
Person類:

import javax.inject.Named;

@Named
public class Person {
	private String name;

	public Person() {
		System.out.println("---這是人的構造函數---");
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
House類:

@Named
public class House {
	@Inject private Person owner;
	public House() {
		System.out.println("---這是房屋構造函數---");
	}

	public Person getOwner() {
		return owner;
	}

	public void setOwner(Person owner) {
		this.owner = owner;
	}
}
測試類:

public class Test {
	public static void main(String[] args) {
		ApplicationContext context = SpringUtil.getApplicationContext(
				"test/spring/inject/bean-inject.xml");
		House house = (House)context.getBean("house");
		Person p = house.getOwner();
		p.setName("張三");
		System.out.println(house.getOwner().getName());
	}
}
輸出結果:

---這是房屋構造函數---
---這是人的構造函數---
張三

    上述例子在Spring3.1下測試成功,在Spring3.1下,每個構造函數只初始化一次及默認的單例形式,個人感覺如果脫離Spring環境應該每次用都會實例化新的對象,當然根據實現的jar包不同而不同,要不javax.inject下的@Singleton註解就沒有什麼用途了。

@Named

    @Named和Spring的@Component功能相同。@Named可以有值,如果沒有值生成的Bean名稱默認和類名相同。

    例如:

@Named public class Person
    該bean的名稱就是person。

@Named("p") public class Person
    如果指定名稱,那麼就是指定的名稱嘍。

@Qualifier

    任何人都可以定義一個新的修飾語,一個qualifier註解應該滿足如下條件:

  • 定義的註解類有@Qualifier,@Retention(RUNTIME)和@Documented。
  • 可以有屬性
  • 可以是公共API的一部分
  • 可以用@Target註解限定使用範圍

    下面是Qualifier的例子:

Genre註解類:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
@Target(value = {ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
public @interface Genre {
	User user() default User.STUDENT;
	public enum User {STUDENT, TEACHER}
}
用戶接口:(對個數進行統計)

public interface IUserDAO {
	int count();
}
StudentDAO:

@Named
@Genre(user = User.STUDENT)
public class StudentDAO implements IUserDAO{
	@Override
	public int count() {
		System.out.println("----StudentDAO----");
		return 0;
	}

}
TeacherDAO:

@Named
@Genre(user = User.TEACHER)
public class TeacherDAO implements IUserDAO {

	@Override
	public int count() {
		System.out.println("--TeacherDAO--");
		return 0;
	}
}
UserDAOProcessor:

@Named
public class UserDAOProcessor {
	/*對TeacherDAO類的注入,如果對StudentDAO類注入應該是:@Genre(user = User.STUDENT)或@Genre,因爲@Genre默認的是STUDENT*/
	@Inject
	private @Genre(user = User.TEACHER) IUserDAO userDAO; 

	public int count() {
		return userDAO.count();
	}

	public IUserDAO getUserDAO() {
		return userDAO;
	}

	public void setUserDAO(IUserDAO userDAO) {
		this.userDAO = userDAO;
	}
}


測試類:

public class Test {
	public static void main(String[] args) {
		ApplicationContext context = SpringUtil.getApplicationContext(
				"test/spring/inject/bean-inject.xml");
		UserDAOProcessor processor = (UserDAOProcessor)context.getBean("userDAOProcessor");
		System.out.println(processor.count());
	}
}
輸出結果:

--TeacherDAO--
0

    個人對@Qualifier的理解:

  1. 和Spring的@Qualifier大致相同
  2. 單獨用@Inject無法滿足對接口的注入,無法找到哪個具體類,所以用@Qualifier來確定注入的具體類
  3. 用到@Qualifier的註解中可以有值、無值和用枚舉類型

@Singleton

    使用該註解標記該類只創建一次,不能被繼承。一般在類上用該註解。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章