CDIのjavax.enterprise.inject.Instanceについてメモ

javax.enterprise.inject.Instance についてメモ。

#環境
##Weld
1.1.10

#実装
##カスタム限定子
```java:MyQualifier.java
package cdi.instance;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.inject.Qualifier;

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyQualifier {
}
```

##インターフェースとその実装クラス
```java:MyInterface.java
package cdi.instance;

public interface MyInterface {
    void execute();
}
```

```java:Hoge.java
package cdi.instance;

public class Hoge implements MyInterface {
    @Override
    public void execute() {
        System.out.println("hoge");
    }
}
```

```java:Fuga.java
package cdi.instance;

@MyQualifier
public class Fuga implements MyInterface {
    @Override
    public void execute() {
        System.out.println("fuga");
    }
}
```

##実行用クラス
```java:Main.java
package cdi.instance;

import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;

import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;

public class Main {
    
    public static void main(String[] args) {
        Weld weld = new Weld();
        WeldContainer container = weld.initialize();
        
        Main main = container.instance().select(Main.class).get();
        main.execute();
        
        weld.shutdown();
    }
    
    @Inject @Any Instance<MyInterface> instanceWithAny;
    @Inject      Instance<MyInterface> instanceWithOutAny;
    
    public void execute() {
        MyInterface obj;
        
        // @Any あり
        obj = instanceWithAny.select(Hoge.class).get();
        obj.execute();
        
        obj = instanceWithAny.select(Fuga.class).get();
        obj.execute();
        
        // @Any なし
        obj = instanceWithOutAny.select(Hoge.class).get();
        obj.execute();
        
        obj = instanceWithOutAny.select(Fuga.class).get();
        obj.execute();
    }
}
```

##実行結果
```text:実行結果
hoge
fuga
hoge
Exception in thread "main" org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001308 Unable to resolve any beans for Types: [class cdi.instance.Fuga]; Bindings: [QualifierInstance{annotationClass=interface javax.enterprise.inject.Default, values={}, hashCode=974519704}]
	at org.jboss.weld.manager.BeanManagerImpl.getBean(BeanManagerImpl.java:699)
	at org.jboss.weld.bean.builtin.InstanceImpl.get(InstanceImpl.java:102)
	at cdi.instance.Main.execute(Main.java:39)
	at cdi.instance.Main.main(Main.java:17)
```

#説明
`javax.enterprise.inject.Instance` とは、型引数で指定したクラスを継承したクラスのインスタンスを CDI のコンテナから取得するための API 的なもの。

```java:
@Inject Instance<MyInterface> instance;
```

上記の場合は、 `MyInterface` を継承したクラスのインスタンスを、 `instance` から取得できる。

##@Any について
```java:@Anyのありなしについて
    @Inject @Any Instance<MyInterface> instanceWithAny;
    @Inject      Instance<MyInterface> instanceWithOutAny;
```

`@Any` は、カスタム限定子を設定したクラスも抽出対象にするかどうかを制御するためのもの。

`@Any` が付いている場合は、カスタム限定子が付与されているクラスも抽出対象になる。
一方、 `@Any` が付いていない場合は、カスタム限定子を付与したクラスは抽出対象外になり、無理に取得しようとすると例外がスローされる。

#参考
+ [Programmatic CDI | Akira Koyasus WebLog](http://www.akirakoyasu.net/2012/12/16/programmatic-cdi/)