スプリング)依存自動注入(@Autowired)


自動注入とは?


前述したSpringDIの設定クラスでは,コンストラクション関数やメソッドを用いて依存オブジェクトを注入した.
@Configuration
public class AppCtx {

    @Bean
    public MemberDao memberDao() {
    	return new MemberDao();
    }
    
    @Bean
    public ChangePasswordService changePwdSvc() {
    	ChangePasswordService pwdSvc = new ChangePasswordService();
        pwdSvc.setMemberDao(memberDao());
        return pwdSvc;
    }
    
    ...
}
設定コードから依存オブジェクトを直接注入しません.

スプリングが依存する空のオブジェクトを自動的に注入する機能もあります!


これを自動注入といいます


スプリング3または4バージョンの初期には自動注入に依存するのはよくなかったが、スプリングが起動するにつれて依存自動注入を用いる傾向が変化したという.
スプリングに依存する自動注入を設定するには、@Autowiredプレゼンテーションまたは@Resourceプレゼンテーションを使用します.
この記事では、@Autowiredアニメーションの使い方を見てみましょう.

@Autowired依存項目の自動注入


自動注入機能を使用すると、スプリングが依存オブジェクトを指定することなく、必要な依存空オブジェクトを検索して注入できます.
自動注入機能を使うのは簡単です.
依存するオブジェクトに@Autowiredコメントを貼り付けるだけです.
@Autowiredコメントが追加されている場合は、設定クラスに依存項目を個別に入力する必要はありません.

@Autowiredプレゼンテーションはメソッドにも添付できます。


空のオブジェクトのメソッドに@Autowiredコメントを追加します.
スプリングはメソッドを呼び出し、メソッドパラメータタイプに対応する空のオブジェクトを検索してパラメータとして注入します.
ただし、@Autowiredプレゼンテーションを適用するオブジェクトが1つだけではない場合はどうなりますか?🤔

1.一致しない空

NoSuchBeanDefinitionException: No qualifyinh bean of type ... available: expected at least 1 beanのような異常が発生しました.

2.一致する2つ以上の空

NoUniqueBeanDefinitionException: No qualifyinh bean of type ... available: expected single matching bean but found 2のような異常が発生しました.
📌 自動注入を行うには、このタイプの空格子点がどのような空格子点であるかを正確に限定できる必要がある.

💡 自動注入する空を指定する方法、@Qualifier


一致する2つ以上の空がある場合は、@Qualifier Anotationで自動的に注入する空を指定できます.
このシミュレーションは自動注入オブジェクトの周波数を制限することができる.
@Qualifierプレゼンテーションは2つの場所で使用できます.

1.@Bean宣言の空の設定方法


次の設定例を見て、理解してください.
import ...


@Configuration
public class AppCtx {
	
    ...
    
    @Bean
    @Qualifier('printer')
    public MemberPrinter memberPrinter1() {
    	return new MemberPrinter();
    }
    
    @Bean
    public MemberPrinter memberPrinter2() {
    	return new MemberPrinter();
    }
    
    ...
    
}
上記のコードでは、memberPrinter1()メソッドにprinter値を持つ@Qualifierコメントを追加しました.この設定は、空の値の制限値としてprinterを指定します.
指定した制限値は、次の場所で使用されます.

2.@Autowiredプレゼンテーションで自動入力するスペースの位置を指定

public class MemberListPrinter {
	
    private MemberDao memberDao;
    private MemberPrinter printer;
    
    ...
    
    @Autowired
    @Qualifier("printer")
    public void setMemberPrinter(MemberPrinter printer) {
    	this.printer = printer;
    }
}
setMemberPrinter()メソッドに@Autowiredコメントが追加されたため、MemberPrinterタイプの空が自動的に注入されます.
@Qualifier宣言値はprinterです.
依存注入候補として、printerに限定された値の空を使用します.

💡 空の名前とデフォルトの制限子


空の設定に@Qualifierプレゼンテーションがない場合は、空の名前を修飾子として指定します.

親/子タイプの関係と自動注入


まず例を見てみましょう.次のクラスは、Carクラスを継承するMclarenクラスです.
public class Mclaren extends Car {

    @Override
    public void print(Car car) {
    	System.out.printf("차 정보: 이름=%s, 출시년도=%s\n", 
        		car.getName(), car.getRelease());
    }
}
次の設定クラスでは、carPrinter 1()メソッドはCarタイプの空のオブジェクトを設定し、carPrinter 2()メソッドはMclarenタイプの空のオブジェクトを設定します.@Qualifierコメントは追加されません.
@Configuration
public class AppCtx {

	...
    
    @Bean
    public Car carPrinter1() {
    	return new Car();
    }
    
    @Bean
    public Mclaren carPrinter2() {
    	return new Mclaren();
    }
    
    ...
    
}
2つのクラスCarListPrinterとCarInfoPrinterがCarタイプの空のオブジェクトに自動的に注入する場合、Mainが2つのクラスを使用して車に関する情報を出力しようとすると、NoUniqueDefinitionExceptionが発生する.

🤔 どうしたんですか。


MclarenクラスはCarクラスを継承しているので、MclarenクラスもCarクラスに割り当てることができます!


スプリングコンテナがCarタイプの空を自動的に注入する必要がある@Autowiredコメントに遭遇した場合、CarPrinter 1(Carタイプ)空とCarPrinter 2(Mclarenタイプ)空のどちらを注入するか分からないため、異常が発生します.
したがって、CarListPrinterクラスとCarInfoPrinterクラスは、@Qualifier宣言によって、どのスペースを入力する必要があるかを定義する必要があります.
まず,CarListPrinterクラスで,@Qualifier宣言により注入するスペースを限定する.
@Configuration
public class AppCtx {

	...
    
    @Bean
    @Qualifier("printer")
    public Car carPrinter1() {
    	return new Car();
    }
    
    ...
    
}

public class CarListPrinter {

	...
    
    @Autowired
    @Qualifier("printer")
    public void setCar(Car car) {
    	this.car = car;
    }
}
そして、自動注入CarInfoPrinterクラスのCarタイプ空を2つの方法で処理することができる.1つ目は上のCarListPrinterのように@Qualifierを使う方法です.
@Configuration
public class AppCtx {

	...
    
    @Bean
    @Qualifier("mcprinter")
    public Car carPrinter2() {
    	return new Car();
    }
    
    ...
    
}

public class CarInfoPrinter {

	...
    
    @Autowired
    @Qualifier("mcprinter")
    public void setCar(Car car) {
    	this.car = car;
    }
}
2つ目の方法は、CarInfoPrinterがMclarenを使用することを変更することです.MclarenタイプのVINは1つしか存在しないので異常は発生しません.
public class CarInfoPrinter {
	...
    
    @Autowired
    public void setCar(Mclaren mcCar) {
    	this.car = car;
    }
}

@Autowiredアニメーションが必要かどうかを設定する3つの方法


@Autowired自動テスト@Autowired自動テストタイプに対応する空白がほとんどなく、異常が発生します.ただし、場合によってはエクスポートする必要はなく、nullなどとして受け入れるだけで、自動注入のオブジェクトは必要ありません.
この場合、@Autowiredコメントが必要かどうかを調整するには、3つの方法があります.

1. @Autowired(required = false)


@Autowiredアニメーションのrequiredアトリビュートをfalseとして指定すると、一致するスペースがなくても書き出しは発生せず、自動注入は実行されません.

2.Java 8のオプション


Spring 5のリリースでは、@Autowiredで宣言されたrequiredプロパティをfalseに設定する必要はありません.java 8のオプションを使用して、依存注入ターゲットを次のように設定できます.
public class MemberPrinter {
	
    private DateTimeFormatter dateTimeFormatter;
    
    public void print(Member member) {
    	...
    }
    
    @Autowired
    public void setDateFormatter(Optional<DateTimeFormatter> formatterOpt) {
    	if (formatterOpt.isPresent()) {
        	this.dateTimeFormatter = formatterOpt.get();
        } else {
        	this.dateTimeFormatter = null;
        }
    }
    
}
オートインジェクションターゲットタイプがOptionの場合は、次の操作を行います.
  • に一致するNull値が存在しない場合、
  • は、値のないオプションをパラメータとして渡す.
  • 一致する空が存在する場合、
  • は、空を値とするオプションをパラメータとして渡す.

    3.@Nullable Anotation


    コメントを追加すると、次の操作が実行されます.
  • に自動的に注入する空がある場合、その空をパラメータとして
  • に渡す.
  • に自動注入の空がない場合、nullをパラメータとして
  • が伝達する.

    💡 @Autowired(require=false) vs. @Nullable


    @Nullableプレゼンテーションを使用すると、自動注入する空が存在しなくてもメソッドが呼び出されます.逆に,@Autowiredプレゼンテーションではrequireのプロパティはfalseであり,ターゲット空間が存在しない場合setterメソッドは呼び出されない.
    上記の3つの方法はフィールドにも適用されます.
    📌 設定クラスでsetterメソッドを使用して依存性を注入する場合、このsetterメソッドに@Autowiredコメントを追加すると、一致する空が自動的に注入されます.
    したがって、@Autowiredコメントを使用する場合は、設定クラスにオブジェクトを注入するよりも、スプリングで提供される自動注入機能を使用します.