@Configuration アノテーションはクラスにアノテーションを付けることができます。クラスにアノテーションが付けられると、Spring は @Configuration アノテーションが付けられたクラスを自動的にスキャンし、IOC コンテナに登録します。そして Bean オブジェクトにインスタンス化されます。
@Configuration アノテーションが付与されたクラスに、@Bean アノテーションが付与された特定のクラスオブジェクトを作成するメソッドが含まれている場合、Spring は自動的に @Bean アノテーションが付与されたメソッドを実行し、対応する Bean 定義情報を IOC コンテナに登録し、インスタンス化されました。
@Configuration アノテーションは、Spring がアノテーション駆動開発をサポートできるようにする Spring 3.0 バージョン以降に追加されたアノテーション型のアノテーションで、主にクラスへのアノテーションに使用されます。クラスに @Configuration アノテーションが付いている場合、このクラスが Spring 構成クラスであることを意味します。 @Configuration アノテーションは Spring の applicationContext.xml ファイルを置き換えることができ、@Configuration アノテーションが付けられたクラスは自動的に IOC コンテナに登録され、インスタンス化されます。
ソース コードの詳細については、org.springframework.context.annotation.Configuration を参照してください。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration { @AliasFor(annotation = Component.class) String value() default ""; // Since: 5.2 boolean proxyBeanMethods() default true; // Since: 6.0 boolean enforceUniqueMethods() default true; }
@Configuration アノテーションの各属性の意味は次のとおりです:
value: Spring IOC コンテナに格納されている Bean の ID。
proxyBeanMethods: Spring 5.2 以降 @Configuration アノテーションに追加され、@Configuration アノテーションが付けられた構成クラスがプロキシされ、構成内で @Bean アノテーションを使用して生成されるかどうかを示します。 class Bean オブジェクトが IOC コンテナ内のシングルトン オブジェクトであるかどうか、値は true または false です。値が true の場合、フル (グローバル) モードを示します。このモードでは、@Configuration アノテーションが付けられた構成クラスがプロキシされます。構成クラス内の @Bean アノテーションを使用して IOC コンテナーに注入される Bean オブジェクトはシングルトン モードです。 @Bean アノテーションが付けられたメソッドを何度呼び出しても、同じ Bean オブジェクトが返されます。値が false の場合、lite (軽量) モードを示します。このモードでは、@Configuration アノテーションが付けられた構成クラスはプロキシされません。構成クラスの @Bean アノテーションを使用して IOC コンテナに注入される Bean オブジェクトは、サンプル モードでは、@Bean アノテーションが付けられたメソッドが呼び出されるたびに、新しい Bean オブジェクトが返されます。デフォルト値は true です。
enforceUniqueMethods: Spring 6.0 以降 @Configuration アノテーションに追加され、@Bean アノテーションが付けられたメソッドが一意のメソッド名を持つ必要があるかどうか、値は true または false を指定します。値が true の場合、@Bean アノテーションが付けられたメソッドには一意のメソッド名があり、これらのメソッド名は重複しないことを意味します。値が false の場合、@Bean アノテーションが付けられたメソッド名が一意ではなく、重複する危険性があることを意味します。デフォルト値は true です。
@Configuration アノテーションのソース コードからも、@Configuration アノテーションが本質的に @Component アノテーションであることがわかります。そのため、構成クラス自体に @ のアノテーションが付けられています。設定アノテーションも IOC コンテナに登録されます。同時に、@Configuration アノテーションも @ComponentScan アノテーションによってスキャンされます。
Spring アノテーションに基づいてアプリケーションを開発する場合、特定のクラスに @Configuration アノテーションを付けることができます。クラスに @Configuration アノテーションが付けられている場合、そのクラスは構成クラスであることを意味します。このクラスの @Bean アノテーションを使用して、Bean オブジェクトを IOC コンテナに注入できます。また、@Autowired、@Inject、および注入する @Resource アノテーション 必須の Bean オブジェクト。
注: Spring のアノテーション モードに基づいてアプリケーションを開発する場合、AnnotationConfigApplicationContext クラスを使用して IOC コンテナを作成する場合は、次の点に注意する必要があります。
(1)呼び出しは AnnotationConfigApplicationContext クラスに渡されます Class 型変数パラメーターのコンストラクターは IOC コンテナーの作成に使用されます。つまり、 @Configuration アノテーションが付けられた構成クラスの Class オブジェクトが IOC コンテナーの作成に渡されます。構成クラスに付加されるアノテーションは省略可能です。
@Configuration アノテーションが受信構成クラスで省略されている場合、構成クラス内の @Bean アノテーションが付けられたメソッドが呼び出されるたびに、異なる Bean インスタンス オブジェクトが返されます。
AnnotationConfigApplicationContext クラスの Class 型の変数パラメータを渡すコンストラクタメソッドのソースコードは以下のとおりです。
public AnnotationConfigApplicationContext(Class<?>... componentClasses) { this(); register(componentClasses); refresh(); }
(2) AnnotationConfigApplicationContext クラスの Class 型の変数パラメータを渡すコンストラクタメソッドのソースコードAnnotationConfigApplicationContext クラスは IOC コンテナを作成するメソッドと呼ばれます。つまり、IOC コンテナを作成するアプリケーションのパッケージ名を渡すことを意味します。構成クラスにマークされた @Configuration アノテーションは省略できません。
AnnotationConfigApplicationContext クラスの String 型変数パラメーターを渡すコンストラクターのソース コードは次のとおりです:
public AnnotationConfigApplicationContext(String... basePackages) { this(); scan(basePackages); refresh(); }
proxyBeanMethods 属性は、値 true または false を取ることができます。値が true の場合、@Configuration アノテーションが付与されたクラス内の @Bean アノテーションが付与されたメソッドを何度呼び出しても、同じ Bean オブジェクトが返されます。 falseの場合、@Configurationアノテーションが付与されたクラスで@Beanアノテーションが付与されたメソッドが呼び出されるたびに、異なるBeanオブジェクトが返されます。
1.1 proxyBeanMethods の値が true であることを確認します
(1) パーソン クラスを作成します
パーソン クラスは主に、IOC コンテナへの登録とオブジェクトのインスタンス化に使用されます。
public class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
(2) ConfigurationAnnotationConfig クラスの作成
ConfigurationAnnotationConfig类的作用就是充当程序启动的配置类,会在ConfigurationAnnotationConfig类上标注@Configuration注解,说明ConfigurationAnnotationConfig类是Spring启动时的配置类。
@Configuration public class ConfigurationAnnotationConfig { @Bean public Person person(){ return new Person(); } }
可以看到,在ConfigurationAnnotationConfig类上标注了@Configuration注解,由于@Configuration注解中的proxyBeanMethods属性默认为true,所以在ConfigurationAnnotationConfig类上的@Configuration注解省略了proxyBeanMethods属性。
(3)创建ConfigurationAnnotationTest类
ConfigurationAnnotationTest类的作用就是整个案例程序的启动类,对整个案例程序进行测试。
public class ConfigurationAnnotationTest { private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationAnnotationTest.class); public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigurationAnnotationConfig.class); ConfigurationAnnotationConfig config = context.getBean(ConfigurationAnnotationConfig.class); Person person1 = config.person(); Person person2 = config.person(); LOGGER.info("person1 == person2 ===>> {}", (person1 == person2)); } }
可以看到,在ConfigurationAnnotationTest类的main()方法中,首先基于AnnotationConfigApplicationContext常见了IOC容器context,从context中获取了ConfigurationAnnotationConfig类的Bean实例对象config,接下来,调用两次config的person()方法分别赋值给Person类型的局部变量person1和person2,最后打印person1是否等于person2的日志。
(4)测试案例
运行ConfigurationAnnotationTest类的main()方法,输出的结果信息如下所示。
person1 是否等于 person2 ===>> true
通过输出的结果信息可以看出,person1是否等于person2输出的结果为true。说明当@Configuration注解中的proxyBeanMethods属性为true时,每次调用使用@Configuration注解标注的类中被@Bean注解标注的方法时,都会返回同一个Bean实例对象。
1.2 验证proxyBeanMethods取值为false的情况
验证@Configuration注解中的proxyBeanMethods属性为false的情况,与验证proxyBeanMethods属性为true的情况的案例程序基本一致,只是将ConfigurationAnnotationConfig类上标注的@Configuration注解的proxyBeanMethods属性设置为false,案例实现的具体步骤如下所示。
(1)修改proxyBeanMethods属性的值
@Configuration(proxyBeanMethods = false) public class ConfigurationAnnotationConfig { @Bean public Person person(){ return new Person(); } }
(2)测试案例
运行ConfigurationAnnotationTest类的main()方法,输出的结果信息如下所示。
person1 是否等于 person2 ===>> false
从输出的结果信息可以看出,person1是否等于person2输出的结果为false。说明当@Configuration注解中的proxyBeanMethods属性为false时,每次调用使用@Configuration注解标注的类中被@Bean注解标注的方法时,都会返回不同的Bean实例对象。
调用AnnotationConfigApplicationContext类的构造方法传入配置类的Class对象创建IOC容器时,可以省略配置类上的@Configuration注解,案例的具体实现步骤如下所示。
(1)删除@Configuration注解
public class ConfigurationAnnotationConfig { @Bean public Person person(){ return new Person(); } }
(2)测试案例
运行ConfigurationAnnotationTest类的main()方法,输出的结果信息如下所示。
person1 是否等于 person2 ===>> false
从输出的结果信息可以看到,输出了person1是否等于person2的结果为false。说明调用AnnotationConfigApplicationContext类的构造方法传入配置类的Class对象创建IOC容器时,可以省略配置类上的@Configuration注解,此时每次调用配置类中被@Bean注解标注的方法时,都会返回不同的Bean实例对象。
调用AnnotationConfigApplicationContext类的构造方法传入包名创建IOC容器时,不能省略配置类上的@Configuration注解,案例的具体实现步骤如下所示。
(1)修改测试类
修改ConfigurationAnnotationTest类的main()方法中,创建AnnotationConfigApplicationContext对象的代码,将调用传入Class对象的构造方法修改为调用传入String对象的方法,修改后的代码如下所示。
public class ConfigurationAnnotationTest { private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationAnnotationTest.class); public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.lwk.demo.spring.annocation.configuration.config"); ConfigurationAnnotationConfig config = context.getBean(ConfigurationAnnotationConfig.class); Person person1 = config.person(); Person person2 = config.person(); LOGGER.info("person1 是否等于 person2 ===>> {}", (person1 == person2)); } }
(2)删除@Configuration注解
public class ConfigurationAnnotationConfig { @Bean public Person person(){ return new Person(); } }
(3)测试案例
运行ConfigurationAnnotationTest类的main()方法,可以看到程序抛出了异常信息,如下所示。
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'io.binghe.spring.annotation.chapter01.configuration.config.ConfigurationAnnotationConfig' available
从输出的结果信息可以看出,调用AnnotationConfigApplicationContext类的构造方法传入包名创建IOC容器时,不能省略配置类上的@Configuration注解,否则会抛出NoSuchBeanDefinitionException。
(4)添加@Configuration注解
@Configuration public class ConfigurationAnnotationConfig { @Bean public Person person(){ return new Person(); } }
(5)再次测试案例
再次运行ConfigurationAnnotationTest类的main()方法,输出的结果信息如下所示。
person1 是否等于 person2 ===>> true
出力結果情報からもわかるように、person1 と person2 が等しいかどうかの出力結果は true となっていますが、こちらも AnnotationConfigApplicationContext クラスのコンストラクタメソッドを呼び出し、パッケージ名を渡して IOC を作成すると、コンテナの場合、設定クラスの @ は省略できません。
以上がJava での @Configuration の使用シナリオは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。