spring: @Resource と @Autowired の違いと推奨される使用方法

@リソース

使い方は @Autowired と似ていますが、依存関係の注入も行い、コンテナから Bean やプロセスを自動的に取得します。

  1. 春を開始すると、コンテナが最初に開始されます。
  2. Spring コンテナを起動すると、デフォルトでコンテナのスキャン範囲内でロード可能な Bean が検索され、プロパティとメソッドに @Resource アノテーションが付いている Bean が特定されます。@Resource アノテーションが見つかったら、3 番目のステップに入ります。
  3. @Resource アノテーションの大括弧内の name 属性が空かどうかを確認します。
    • 空の場合: Springコンテナ内のBeanのIDが、@Resourceでアノテーションを付ける変数属性名と同じかどうかを確認します。
      • それらが同じであれば、一致は成功します。
      • 異なる場合は、Spring コンテナ内の Bean ID に対応する型が、@Resource でアノテーションが付けられる変数属性に対応する型と等しいかどうかを確認します。
        • それらが等しい場合、マッチングは成功します。
        • 等しくない場合、一致は失敗します。
    • 空でない場合は、name の属性値がコンテナ内の Bean の ID 名と等しいかどうかを確認します。
      • 等しい場合、一致は成功します。
      • 等しくない場合、一致は失敗します。

/*纳入容器中后,bean的id名字为ps*/
@Component(value="ps")
public class Person {
    
    
}

注釈の name 属性が空ではありません

@Component
public class Man {
    
    
    /*
    从容器中取id名字为ps的bean,
    如果找不到该bean,spring启动过程中就会报错,表示把Man类型的bean注入到容器中不成功,
    	因为person的属性依赖注入的时候就出错了,
    	所以创建Man的bean的时候肯定不成功。
    */
    @Resource(name="ps")
    private Person person;

    /*
    依赖注入失败,
    	因为Person类型注入到容器中的bean的id指定为ps,
    	所以从容器中获取id为person的bean就会失败
    */
    //  @Resource(name="person")
    //  private Person ps;
}

アノテーションの name 属性が空です

注釈付きの変数属性は、コンテナ内の Bean ID の名前と同じです。
@Component
public class Man {
    
    

    /*
    @Resource注解的属性变量ps与容器中的bean的id名字ps相等,
    可以匹配
    */
    @Resource
    private Person ps;

}
アノテーション付きの変数属性は、コンテナ内の Bean ID の名前と等しくありません。
@Component
public class Man {
    
    

    /*
    @Resource注解的属性变量ps与容器中的bean的id名字ps不相等,然后通过bean的类型判断:
    	person变量属性的类型为Person类,
    	容器中的id为ps的bean的类型也为Person类型,
    	因此此种情况下也可以匹配
    */
    @Resource
    private Person person;

}

@Autowired

次のように使用します

@Autowire
private JdbcTemplate jdbcTemplate;

アイデアには次のようなプロンプト メッセージが表示されます。これは、属性フィールド挿入の方法は推奨されません。検出された問題は次のとおりです: Spring チームは次のことを推奨しています: 「常に Bean 内でコンストラクターベースの依存関係注入を使用し、必須の依存関係には常にアサーションを使用します」

Field injection is not recommended Inspection info: Spring Team recommends: "Always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencies".

注入法

Spring Framework (5.0.3) のドキュメントでは、2 つの主要な注入タイプのみが定義されています。以下でさらに細分化します:Setter ベースの依存関係注入 2 つに分割 < a i=2> と 基于Setter的依赖注入基于字段的依赖注入

コンストラクターベースの依存関係の注入

public class AServiceImpl implents AService{
    
    
    private ADao aDao;
    
    @Autowire
    public AServiceImpl(ADao aDao){
    
    
        this.aDao = aDao;
    }
}

セッターベースの依存関係の注入

public class AServiceImpl implents AService{
    
    
    private ADao aDao;
    
    @Autowire
    public setADao(ADao aDao){
    
    
        this.aDao = aDao;
    }
}

フィールドベースの依存関係の注入

この注入方法ではアイデアに警告が発生しますが、その理由は上記で説明しています。

public class AServiceImpl implents AService{
    
    
	@Autowire
    private ADao aDao;
}

フィールドベースの依存関係注入の欠点は次のとおりです。

  1. 对于有final修饰的变量不好使

    • Spring の IOC はプロパティ注入に set 形式を使用しますが、最終型変数はクラス コンストラクターを呼び出すプロセス中に初期化する必要があります。
    • これは、フィールドベースの依存関係注入では実行できないことです。 コンストラクターベースの依存関係注入のみを使用できます
  2. 掩盖单一职责的设计思想: OOP 設計には単一責任の考え方があります。

    • コンストラクターベースの依存関係注入を使用して Spring の IOC を使用する場合、パラメーターを注入しすぎると、コンストラクターのパラメーターが非常に大きくなります。
    • フィールドベースの依存関係注入を使用しても気づかず、@Autowire にどっぷり浸かることになります。
    • サンプルコードは次のとおりです
      public class VerifyServiceImpl implents VerifyService{
              
              
          
        private AccountService accountService;
        private UserService userService;
        private IDService idService;
        private RoleService roleService;
        private PermissionService permissionService;
        private EnterpriseService enterpriseService;
        private EmployeeService employService;
        private TaskService taskService;
        private RedisService redisService;
        private MQService mqService;
      
        public SystemLogDto(AccountService accountService, 
                            UserService userService, 
                            IDService idService, 
                            RoleService roleService, 
                            PermissionService permissionService, 
                            EnterpriseService enterpriseService, 
                            EmployeeService employService, 
                            TaskService taskService, 
                            RedisService redisService, 
                            MQService mqService) {
              
              
            this.accountService = accountService;
            this.userService = userService;
            this.idService = idService;
            this.roleService = roleService;
            this.permissionService = permissionService;
            this.enterpriseService = enterpriseService;
            this.employService = employService;
            this.taskService = taskService;
            this.redisService = redisService;
            this.mqService = mqService;
        }
      }
      
  3. 与Spring的IOC机制紧密耦合

    • すべての制御を Spring の IOC に与えます。他のクラスはインジェクション プロパティの 1 つをリセットしようとしていますが、それを処理できません。 (もちろん、反省することもできます)
    • Spring の目的は、分離と依存関係の逆転です。その結果、クラス インジェクター (この場合は Spring) と再度結合することで、クラス フィールドを自動配線する機能が失われます。クラスの分離が実装され、Spring コンテナの外ではクラスが無効になりました。
  4. 隐藏依赖性

    • Spring の IOC を使用する場合、被注入的类应当使用一些public类型(构造方法,和setter类型方法)的方法来向外界表达:我需要什么依赖
    • フィールドベースの依存性注入手法、基本都是private形式的,private把属性都给封印到class当中
  5. 无法对注入的属性进行安检

    • フィールドベースの依存関係注入メソッドでは、プログラムの開始時にこのクラスを取得することはできません。実際のビジネスで使用される場合にのみ取得されます。通常の状況では、この注入されたクラスは null ではありません。
    • null の場合はどうなるでしょうか? エラーは業務処理中にのみ表示されるため、少し遅れますが、起動時に表示されれば、すぐにバグを修正できます (もちろん、検証用のアノテーションを追加することもできます)。

違い

1 つ: @Autowired と @Resource の両方を使用して Bean を組み立てることができます。どちらもフィールドまたはセッター メソッドに書き込むことができます。

2 つ: @Autowired默认按类型装配 (このアノテーションは 属于spring に属します)、默认情况下必须要求依赖对象必须存在

  1. 必要に応じて允许null 值、必須属性を false に設定できます
    @Autowired(required=false)
    
  2. 必要に応じて使用名称装配结合@Qualifier注釈を付けて使用できます
    @Autowired
    @Qualifier("baseDao")     
    private BaseDao baseDao;  
    

3 つの @Resource (このアノテーション 属于J2EE)、默认安照名称装配、名前は 通过name属性进行指定、 です。

  1. If没有指定name属性、フィールドに注釈が書き込まれたとき、默认取字段名进行按照名称查找
  2. 注釈が記述されている場合在setter方法上默认取属性名、アセンブリが実行されます。
  3. 找不到与名称匹配的bean时才按照类型进行装配
  4. ただし、name属性一旦指定,就只会按照名称进行装配 であることに注意してください。

要約する

用 @Resource注解在字段上,且这个注解是属于J2EE的,减少了与spring的耦合,这样代码看起就比较优雅

それでも @Autowired を使用したい場合:

  1. 推荐使用基于构造函数和基于setter的依赖注入
  2. for必需的依赖项,建议使用基于构造函数的注入 により、それらを不変にし、null にならないようにします。
  3. のために可选的依赖项,建议使用基于Setter的注入

おすすめ

転載: blog.csdn.net/yyuggjggg/article/details/129131852