1
0

More than 3 years have passed since last update.

Spring基礎 〜DI編〜

Last updated at Posted at 2020-04-13

DIについて

DIとは

直接インスタンスを生成した APPがDIコンテナを経由してインスタンス取得できるようにすること。
DIを利用することでのメリットとして以下があげられる。

  • スコープの制御
  • インスタンスのライフサイクル制御
  • 共通機能の組み込み
  • 疎結合になることでのUTのしやすさ向上

DIコンテナに登録するComponentを「Bean」という。
Configurationのことを「Bean定義」という。

DIを利用した実装方法

Configuration方法
  • JavaベースConfiguration

@Configurationでコンフィギュレーションクラスであることを宣言
@BeanでBean定義

AppConfig.java
@Configuration
public class AppConfig {
    @Bean
    TestRepository testRepo() {
        retrun new TestRepositoryImpl();
    }
}
  • xmlベース

要素でBeanの定義。id属性でbean名、Class属性がそのクラスのBeanのインスタンスとして定義

.xml
<beans>
<bean id="test" class="com.test.TestImpl" />
</beands>
  • アノテーションベース

Bean定義用のアノテーションが付与されたクラスをスキャンしてDIコンテナに登録する(コンポーネントスキャン)手法。
一番直感的に実装できる。

Bean定義側

TestImpl.java
@Component
publi classTestImpl implements Test {
}

利用側
コンストラクタに@Autowiredを付与し、自動インジェクション。

TestImpl.java
@Component
publi class TestUseImpl implements TestUse {
    @AutoWired
    public TestUseImpl(Test test) {
    }
}

インジェクションの種類

3種類方法があるが、コンストラクタインジェクションが良さそう。割愛。
コンスタラクタインジェクションはDIしたインスタンスがfinalになるからおすすめのよう。
https://irof.hateblo.jp/entry/2017/04/16/222737
- Setterインジェクション
- Constructorインジェクション
- fieldインジェクション

オートワイヤリングについて

オートワイヤリングは@Beanなどで明示的にBean定義しなくても自動でDIコンテナにインジェクションされる仕組みのこと。
内部的に型 or 名前 による解決を行っている。
ただし同一の型でDIコンテナに複数定義されているとDIコンテナはどちらを利用するかわらないためエラーとなってしまう。
そんな時に利用するのが@Qualifier@Resouce

QualifierとResouce

以下のように同一のConvertクラスを返却するメソッドをBeanに登録するとする。

AppConfig
@Configuration
@ComponentScan
public class AppConfig {
    @Bean
    Convert getA() {
        return new ConvertA();
    }
    @Bean
    Convert getB() {
        return new ConvertB();
    }

以下のようにインジェクションしようとするとgetAgetBどちらをインジェクションするかpg側は判断できない。

MainService
@Service
public class MainService {
    @Autowired
    private Convert getA;

    public String execute() {
        return getA.getConvert();
    }

以下のような記述でどちらをインジェクションするか明示的に指定することで切り分けることが可能。

@Qualifier("getA")
@Autowired
private Convert getA;
// @Resouceはプロパティ名でコンテナから対象のインスタンスを探しに行くため、
// nameと対象のプロパティ名が一致している場合は、省略することが可能
@Resouce(name = "getA") または、 @Resouce
@Autowired
private Convert getA;

※Resouceはコンストラクタインジェクションでの利用は不可。

ダメな例
@Service
public class MainService {
    private final Convert getA;

    @Resouce(name = "getA")
    public MainService (Convert a) {
        getA = a;
    }

    public String execute() {
        return getA.getConvert();
    }
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0