【Spring】 (3) Springはアノテーションを利用してBeanオブジェクトの格納と読み込みを行う


序文

前回の記事ではSpringオブジェクトの作成とBeanオブジェクトへのアクセス操作を詳しく紹介しましたが、設定ファイルからBeanオブジェクトを登録したり、 や を使ってBeanオブジェクトを取得したりする操作は非常に複雑ApplicationContextですBeanFactoryそこで本記事では、Beanオブジェクトの格納や読み込みをより簡単に実現する方法を中心に詳しく紹介します。

Spring では、Bean オブジェクトをより簡単に保存して使用する場合は注解、 Bean オブジェクトを使用することが中心であり、この記事では主に、アノテーションを使用して Bean オブジェクトへのアクセス操作を実装する方法を示します。

1. アノテーションを使用してBeanオブジェクトを格納する

spring-congig以前にBeanオブジェクトを格納する場合はファイルに一行追加する必要があり<bean>、SpringコンテナにBeanオブジェクトを追加するたびに新たな行を追加する必要があり、非常に面倒であった。

注解ただし、この行の内容を置き換えるには1 つを使用するだけで済み<bean>、現時点では非常に便利です。アノテーションを通じて Spring コンテナにオブジェクトを保存する場合、主に 2 つのタイプのアノテーションがあります。

  1. クラス アノテーションを使用します (アノテーションの 5 つのカテゴリ)。

    • @Controller(保管管理):利用者が要求したデータの正当性を検証するものであり、セキュリティシステムに相当する。
    • @Service(サービス ストレージ): 特定の実行方法を調整およびスケジュールするために使用されます。
    • @Repository(倉庫ストレージ): 永続層、データベースとの交換。
    • @Component(コンポーネントストレージ):ツールに相当。
    • @Configuration(構成ストレージ): プロジェクト内の一部の構成。
  2. 使用上の注意:

    • @Bean: これはメソッドに作用し、上記のクラス アノテーションと組み合わせて使用​​する必要があります。

ただし、その前に設定する必要があります扫描路径

1.1 スキャンパスの設定

spring-config.xmlファイルに次のレコード行を追加します。これは、1 つを指定すること、つまり、Spring コンテナに追加する必要があるすべての Bean オブジェクトが、指定されたパッケージまたはそのサブパッケージの下にあること

を意味します。ここで私が知っているパッケージは です。これは、このパッケージの下にあるBeanオブジェクトでなければ、たとえアノテーションが付いていたとしても、Springコンテナに追加されないことを意味します。base packagebase packagecom.spring.demo

1.2 クラスアノテーションにBeanオブジェクトを格納する

1.2.1 @Controller (コントローラーストレージ)

アノテーションを使用して@ControllerBean オブジェクトを保存します。

@Controller
public class StudentController1 {
    
    
    public void sayHi(){
    
    
        System.out.println("do studentController1 sayHi().");
    }
}

ApplicationContextBean オブジェクトを取得する方法は次のとおりです

public static void main(String[] args) {
    
    
    ApplicationContext context =
            new ClassPathXmlApplicationContext("spring-config.xml");

    StudentController1 studentController1 =
            context.getBean("studentController1", StudentController1.class);

    studentController1.sayHi();
}

关于 Bean 对象的命名规则可见后文。

1.2.2 @Service (サービスストレージ)

アノテーションを使用して@ServiceBean オブジェクトを保存します。

@Service
public class StudentController2 {
    
    
    public void sayHi(){
    
    
        System.out.println("do studentController2 sayHi().");
    }
}

Bean オブジェクトを取得します。

StudentController2 studentController2 =
        context.getBean("studentController2", StudentController2.class);

1.2.3 @Repository (倉庫ストレージ)

アノテーションを使用して@RepositoryBean オブジェクトを保存します。

@Repository
public class StudentController3 {
    
    
    public void sayHi(){
    
    
        System.out.println("do studentController3 sayHi().");
    }
}

Bean オブジェクトを取得します。

StudentController3 studentController3 =
        context.getBean("studentController3", StudentController3.class);

1.2.4 @Component (コンポーネントストレージ)

アノテーションを使用して@ComponentBean オブジェクトを保存します。

@Component
public class StudentController4 {
    
    
    public void sayHi(){
    
    
        System.out.println("do studentController4 sayHi().");
    }
}

Bean オブジェクトを取得します。

StudentController4 studentController4 =
        context.getBean("studentController4", StudentController4.class);

1.2.5 @Configuration (設定ストレージ)

アノテーションを使用して@ConfigurationBean オブジェクトを保存します。

@Configuration
public class StudentController5 {
    
    
    public void sayHi(){
    
    
        System.out.println("do studentController5 sayHi().");
    }
}

Bean オブジェクトを取得します。

StudentController5 studentController5 =
        context.getBean("studentController5", StudentController5.class);

1.2.6 Bean の命名規則

上記のコードから、Bean オブジェクトの作成時には標準の「大きなこぶ」命名方法が使用され、読み取り時には Bean の名前はクラス名の最初の文字が小文字であることがわかります。小さなこぶ。


ただし、この時点でSControllerクラスを作成し、アノテーションを使用して Spring コンテナに追加します。このときの Bean オブジェクトの名前は何になるでしょうか。上記のコードの規則によれば、まだSController?

SController sController = context.getBean("sController", SController.class);

プログラムを実行すると、エラーが見つかりました。

これは、その名前を持つそのような Bean オブジェクトが存在しないことを意味しますsControllerに変更するのがSController正しいでしょうか?


現時点では、ディスカバリーは正常に実行できます。

Bean名生成のソースコード:

  1. Bean 名を検索し、AnnotationBeanNameGeneratorクラスを選択します
  2. 見続ける

  1. 見続ける


4. ソースコード、つまりIntrospectorクラス配下のdecapitalizeメソッド

を見つけます このメソッドは、文字列の最初の文字が大文字であるかどうかをチェックし、2番目の文字も大文字である場合は、小文字処理を行わずに元の文字列を直接返します。これは、略語や頭字語などの特殊なケースが誤って扱われるのを避けるために行われます。

1.3 アノテーションの 5 つのカテゴリの役割

Spring フレームワークで一般的に使用される 5 つのアノテーションは、@Component、@Controller、@Service、@Repository、および @Configuration です。

  • @Component: 一般的なコンポーネントのアノテーション。クラスが Spring 管理のコンポーネント (Bean) であることを示します。

  • @Controller: HTTP リクエストを処理し、レンダリングを表示するために、通常 Spring MVC で使用されるコントローラー クラスを識別するために使用されます。

  • @Service: サービス クラスを識別するために使用され、そのクラスが何らかのビジネス ロジック処理を提供することを示します。

  • @Repository: ウェアハウス クラスを識別するために使用され、このクラスがデータ アクセス (通常はデータベースと対話) に使用されることを示します。

  • @Configuration: 構成クラスを識別するために使用され、そのクラスに Spring 構成情報が含まれていることを示し、通常は@BeanBean を定義するために と一緒に使用されます。

1.3.1 なぜこれほど多くの注釈が存在するのか

上記のコードのデモを通じて、これらのアノテーションの機能は同じであることがわかりました。それらはすべて同じであるのに、なぜこれほど多くの異なるアノテーションが必要なのでしょうか。

Spring が非常に多くのアノテーションを提供する理由は、アプリケーションのコンポーネントと依存関係をより適切に整理および管理するためです各アノテーションには独自の特定の目的があるため、開発者はアプリケーション内のさまざまなタイプのクラスを簡単に識別して区別できます同時に、プログラムのプロジェクト階層も削除されます。

  1. その中には@Controller、ユーザーと対話し、ユーザーが送信したデータの正当性を検証する責任を負う制御層が含まれます。
  2. @Serviceこれは、特定の実行メソッドを手配してディスパッチするために使用されるサービス層を表し、ステーションのサービス デスクに相当します。
  3. @Repository永続層を表します。永続層はデータの永続的なストレージを担当し、通常はデータベースと対話する必要があります。

上記の 3 つのレベルは、プログラムのエンジニアリング階層化を実現し、Java EE 標準階層化の中核となる階層化でもあります。

1.3.2 クラスアノテーション間の関係

  • @Controller / @Service / @Repository / @Configurationや などの注釈のソース コードを確認すると、
    これらはすべて@Componentサブクラスの注釈であり、 と@Controller / @Service / @Repository / @Configurationマークされたクラスも考慮されることを意味します@Component

  • さらに、@Configurationこのアノテーションは、このクラスが Bean を定義し、アプリケーションの他の要素を構成するために使用される Spring 構成クラスであることを示す特別なアノテーションです。構成クラスのアノテーションは@Bean、Bean を定義するために使用されます。

1.4 メソッドアノテーションにBeanオブジェクトを格納する

まず、User エンティティ クラスを作成します。

package com.spring.demo.entity;

/**
 * 普通的用户实体类
 */
public class User {
    
    
    private Integer uid;
    private String username;
    private String password;
    private Integer age;

    public Integer getUid() {
    
    
        return uid;
    }

    public void setUid(Integer uid) {
    
    
        this.uid = uid;
    }

    public String getUsername() {
    
    
        return username;
    }

    public void setUsername(String username) {
    
    
        this.username = username;
    }

    public String getPassword() {
    
    
        return password;
    }

    public void setPassword(String password) {
    
    
        this.password = password;
    }

    public Integer getAge() {
    
    
        return age;
    }

    public void setAge(Integer age) {
    
    
        this.age = age;
    }

    @Override
    public String toString() {
    
    
        return "User{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }
}


1.4.1 @Bean アノテーションの使用

コンポーネント クラスを作成しUserBeans@Beanメソッド アノテーションを使用して User クラスを Spring コンテナに追加します。

@Controller
public class UserBeans {
    
    
    @Bean
    public User getUser(){
    
    
        User user = new User();
        user.setUid(1);
        user.setUsername("王五");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }
}

@Beanメソッド アノテーションを使用する場合、有効にするためには 5 種類のアノテーションを使用する必要があることに注意してください。

Bean オブジェクトを取得します。

public static void main(String[] args) {
    
    
    ApplicationContext context =
            new ClassPathXmlApplicationContext("spring-config.xml");

    User user = context.getBean("getUser", User.class);
    System.out.println(user);
}

メソッド アノテーション を使用する場合@Bean、Bean オブジェクトのデフォルト名は、Spring コンテナに追加されるメソッドの名前であることに注意してください。

1.4.2 Beanオブジェクトの名前変更

たとえば、メソッド名をそのまま Bean オブジェクトの名前として使用する場合、getUser非常に不合理なため、Bean の名前を変更する必要があることがよくあります。しかし、ソース コードを見ると、 or属性が配列であること@Beanがわかります。これは、Bean オブジェクトが複数の名前を取ることができることを意味します。namevalue

例えば:

この時点で、Bean オブジェクトは次の 2 つの名前を通じて取得でき、それらは同じ Bean であることがわかります。

もう 1 つの注意点は、Bean の名前を変更すると、元のデフォルトのメソッド名が無効になることです。

2. アノテーションを使用してBeanオブジェクトを取得する

2.1 アノテーションによるBeanオブジェクトの取得方法

Bean オブジェクトを取得すること对象装配、つまりオブジェクトを取り出して特定のクラスに入れることを とも言い、 とも言います对象注入

オブジェクトインジェクションを実装するには、次の 3 つの方法があります。

  1. プロパティの注入: プロパティの注入は、プロパティのアノテーションを使用して実現されます。一般的な注釈は@Autowiredとです@Resourcesetterプロパティインジェクションは、メソッドを提供せずにBeanオブジェクトのプロパティに直接注入します。

  2. Setterインジェクション:インジェクションはSetter、Bean オブジェクトのメソッドのアノテーションを使用してsetter実現されます。このインジェクションメソッドは、Bean のメソッドを呼び出すときに依存オブジェクトをパラメータとして渡しますsetter

  3. コンストラクタインジェクション: コンストラクタインジェクションは、Bean オブジェクトのコンストラクタのアノテーションを使用して実現されます。このインジェクション方法は、Bean オブジェクトの作成時にコンストラクターのパラメーターを通じて依存オブジェクトを渡す方法です。

2.2 3つの注入方法の使用

実際の開発パターンに従い、ServiceクラスをControllerクラスにインジェクションし、mainメソッドを通じてController内のBeanオブジェクトを取得します。
まずUserServiceクラスとUserControllerクラスを作成します。


@Service
public class UserService {
    
    
    public void sayHi(){
    
    
        System.out.println("hi, userService.");
    }
}

2.2.1 属性の注入

@Controller
public class UserController {
    
    
    // 1. 属性注入
    @Autowired
    private UserService userService;

    public void sayHi(){
    
    
        System.out.println("do userController sayHi().");

        userService.sayHi();
    }
}

2.2.2 セッターインジェクション

@Controller
public class UserController {
    
    
    // 2. setter 注入
    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
    
    
        this.userService = userService;
    }
    
    public void sayHi(){
    
    
        System.out.println("do userController sayHi().");

        userService.sayHi();
    }
}

2.2.3 コンストラクターのインジェクション

@Controller
public class UserController {
    
    
    // 3. 构造方法注入
    private UserService userService;

    // @Autowired
    public UserController(UserService userService) {
    
    
        this.userService = userService;
    }

    public void sayHi(){
    
    
        System.out.println("do userController sayHi().");

        userService.sayHi();
    }
}

この時点でコンストラクターが 1 つしかない場合は@Autowired省略できることに注意してください。

2.3 3 つの注入方法の長所と短所

属性インジェクション

  1. 利点: 簡潔でコードが少なく、属性の直接注入に適しています。
  2. 欠点:
    • 注入する必要があるプロパティの場合、一致する Bean が見つからない場合は実行時エラーが発生します。
    • 互換性は良くありません。IoC コンテナーでのみ使用できます。
    • finally変更された変数の注入を実現する方法はありません。
    • シンプルすぎると、単一の設計原則に違反しやすくなります。

セッター注入:

  1. 利点: 単一の設計原則に従って、各メソッドは 1 つのオブジェクトのみを渡すことができます。

  2. 欠点:

    • finally変更された変数の注入を実現する方法はありません。
    • Setter を使用して挿入されたオブジェクトは変更される可能性があります。

コンストラクターの注入:

  1. アドバンテージ:

    • finally変更された変数を実装して注入を実現できます。
    • 挿入されたオブジェクトは変更されません。つまり、コンストラクターは 1 回しか実行できません。
    • コンストラクターの注入により、注入されたオブジェクトが完全に初期化されることが保証されます。
  2. 欠点: 構築メソッドに多くのパラメーターがある場合、コードは冗長になります。

2.4 @リソースインジェクション

@Autowiredクラス インジェクションを実行するときは、キーワードの使用に加えて、@Resource次のコードに示すように、インジェクションに使用することもできます。

プロパティの注入:

public class UserController {
    
    
    // 1. 属性注入
    @Resource
    private UserService userService;

    public void sayHi(){
    
    
        System.out.println("do userController sayHi().");

        userService.sayHi();
    }
}

セッター注入:


@Controller
public class UserController {
    
    

    // 2. setter 注入
    private UserService userService;
    
    @Resource
    public void setUserService(UserService userService) {
    
    
        this.userService = userService;
    }

    public void sayHi(){
    
    
        System.out.println("do userController sayHi().");

        userService.sayHi();
    }
}

残念ながら、@Resourceコンストラクターの注入はサポートされていません。

2.5 @Autowired と @ Resource の違い

  1. @Autowiredこれは Spring フレームワークによって提供されるアノテーションであり、@ResourceJSR-250 仕様によって提供されるアノテーションではありませんが、Spring もサポートしています。
  2. @AutowiredBean はデフォルトで型ごとにアセンブルされ、複数の型が一致する場合は@Qualifierアノテーションで特定の Bean 名を指定できます。デフォルトでは@Resource、属性名に従ってアセンブルされ、特定の Bean 名は name 属性を通じて指定できます。
  3. @Autowiredこれは Spring 独自のアノテーションであり、より柔軟で強力です。@Resourceより一般的な場合の標準 Java アノテーションです。
  4. @AutowiredSetter注入、コンストラクタ注入、プロパティ注入に使用できます。また、注入とプロパティ注入@Resourceにのみ使用できSetter、コンストラクタ注入には使用できません。

2.6 同じタイプの複数の @Bean の挿入とエラーの報告

同じ型のBeanオブジェクトが複数存在し、アノテーションによって他のBeanオブジェクトに注入する必要がある場合、注入するBeanが明確に指定されていないとエラーが報告されます。

2.6.1 エラー報告の問題

UserBeansたとえば、 User を Controller の Controller からComponent に注入しますUserController

まず、次をUserBeans使用して@Bean2 つの User オブジェクトを Spring コンテナに追加します。

@Controller
public class UserBeans {
    
    
    @Bean(name = {
    
    "user1", "u1"})
    public User getUser1(){
    
    
        User user = new User();
        user.setUid(1);
        user.setUsername("张三");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }

    @Bean(name = "user2")
    public User getUser2(){
    
    
        User user = new User();
        user.setUid(1);
        user.setUsername("李四");
        user.setPassword("123456");
        user.setAge(18);
        return user;
    }
}

Bean オブジェクトを取得するにはUserControllerそれぞれuse@Autowiredとinject を使用します。@Resource

@Autowired:

この時点では、同じ型で名前が異なる Bean オブジェクトが 2 つあるため、アノテーションは@Autowiredどちらのオブジェクトを取得すればよいのかわかりません。

@Resource

アノテーションを使用して@Resourceどのオブジェクトを取得するかを決定することもできません。

Bean オブジェクトを検索する@Autowired順序については、次のとおりです。@Resource

  • @Autowired最初にタイプで検索し、次に名前で検索します。
  • @Resource最初に名前で検索し、次にタイプで検索します。

2.6.2 @Resource(name="XXX") を使用して解決する

@Controller
public class UserController {
    
    

    @Resource(name = "user1")
    private User user;

    public void sayHi(){
    
    
        System.out.println("do userController sayHi().");
    }
}

2.6.3 @Autowired と @Qualifier を使用して解決する

@Controller
public class UserController {
    
    

    @Autowired
    @Qualifier(value = "user1")
    private User user;

    public void sayHi() {
    
    
        System.out.println("do userController sayHi().");
    }
}

おすすめ

転載: blog.csdn.net/qq_61635026/article/details/132080955