この記事は、ChenPiのJavaLibによるHUAWEICLOUDコミュニティ「 AwareSpringBean 」から共有されています。
春の豆を意識する
通常の状況では、SpringのBeanはSpringを認識しません。つまり、作成されたBeanファクトリ(BeanFactory)を認識できず、ファクトリ内のID、つまりbeanNameを認識できず、Springアプリケーションも認識できません。コンテキストオブジェクト(ApplicationContext)など。
Spring Beanにこの情報を認識させたい場合は、何らかの方法でこの情報を取得し、それをBeanインスタンスに設定できます。この方法の欠点は、知覚する必要のある情報を取得し、それをBeanに積極的に設定する必要があることです。これにより、多くの冗長なコードが書き込まれます。ただし、Springから切り離すことができるという利点があります。
もちろん、Springフレームワークは、Beanを認識させるためのこの拡張性を提供します。Beanクラスに特定のインターフェースを実装させ、その中のメソッドをオーバーライドするだけです。このようにして、Springは、Beanのライフサイクルのある段階でこれらのオーバーライドされたメソッドを呼び出し、認識しておく必要のある情報を注入します。この方法の欠点は、Springと組み合わせる必要があることです。利点は、コードの量を減らすことができ、単純であるということです。
認識インターフェース
SpringのBeanがある程度の認識を得るには、共通の親インターフェースであるAwareインターフェースを持つ特定のインターフェースを実装する必要があります。
package org.springframework.beans.factory;
public interface Aware {
}
Awareは、Beanがコールバックメソッドを介してSpringコンテナ内の特定のオブジェクトを取得できることを示すマーカーインターフェイスです。特定のメソッドシグネチャは個々のサブインターフェイスによって定義されますが、通常、単一のパラメータを受け入れてvoidを返すメソッドを1つだけ含める必要があります。
Awareインターフェースを実装するだけでは、デフォルトの機能は提供されないことに注意してください。通常、特定の知覚機能を取得するために、Awareのサブインターフェイスを実装します。
BeanNameAware、BeanFactoryAware、ApplicationContextAware、EnvironmentAware、ApplicationEventPublisherAwareなど、Awareインターフェースには多くのサブインターフェースがあります。一般的な使用法を次に示します。
BeanNameAwareインターフェース
BeanがBeanファクトリで自身のbeanName、つまりSpringコンテナの名前(ID)を知る必要がある場合。このBeanNameAwareインターフェースは実装できます。BeanNameAwareインターフェースのソースコードは次のとおりです。メソッドは1つだけで、beanNameはこのメソッドを介してBeanに設定されます。
package org.springframework.beans.factory;
public interface BeanNameAware extends Aware {
void setBeanName(String name);
}
実際、私たちが使用するBeanは、通常、beanFactoryでその名前を知る必要はありません。これはほとんど意味がありません。一般に、Spring独自のフレームワークを公式に使用する方が多く、BeanがSpring APIに依存するため、公式には使用を推奨していません。
package com.chenpi;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.stereotype.Component;
/**
* @author 陈皮
* @version 1.0
* @description
* @date 2022/4/3
*/
@Component
public class Person implements BeanNameAware {
private String beanName;
@Override
public void setBeanName(String name) {
this.beanName = name;
}
public String getBeanName() {
return beanName;
}
}
次のように検証するテストユニットを作成します。
package com.chenpi;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ApplicationTests {
@Autowired
private Person person;
@Test
public void testValue() {
System.out.println("Person BeanName:" + person.getBeanName());
}
}
// 输出结果如下
Person BeanName:person
BeanFactoryAwareインターフェース
Beanが独自のBeanFactoryオブジェクトを構成する場合は、BeanFactoryAwareインターフェースを実装できます。必要に応じて、BeanはコラボレーションのためにBeanFactoryオブジェクトを介して他のBeanオブジェクトを取得できます。もちろん、この方法はお勧めしません。依存するBeanオブジェクトを注入するには、DIメソッドを使用することをお勧めします。BeanFactoryAwareインターフェースのソースコードは次のとおりです。
package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
public interface BeanFactoryAware extends Aware {
// 在bean属性填充之后,但是在初始回调(例如afterPropertiesSet()方法)之前回调此方法
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
テストコードと単体テストの検証結果は次のとおりです。
package com.chenpi;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.stereotype.Component;
/**
* @author 陈皮
* @version 1.0
* @description
* @date 2022/4/3
*/
@Component
public class Person implements BeanNameAware, BeanFactoryAware {
private String beanName;
private BeanFactory beanFactory;
@Override
public void setBeanName(String name) {
this.beanName = name;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public String getBeanName() {
return beanName;
}
public BeanFactory getBeanFactory() {
return beanFactory;
}
}
package com.chenpi;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ApplicationTests {
@Autowired
private Person person;
@Test
public void testValue() {
System.out.println("Person BeanName:" + person.getBeanName());
System.out.println("Person Bean's BeanFactory:" + person.getBeanFactory().getClass());
System.out.println(
person == person.getBeanFactory().getBean(person.getBeanName(), Person.class));
}
}
// 输出结果如下
Person BeanName:person
Person Bean's BeanFactory:class org.springframework.beans.factory.support.DefaultListableBeanFactory
true
ApplicationContextAwareインターフェース
Spring BeanがSpringコンテナー、つまりApplicationContextオブジェクトを認識する必要がある場合は、ApplicationContextAwareインターフェースを実装できます。他のBeanオブジェクトは、コラボレーションのためにSpringコンテナを介して取得できます。
もちろん、BeanオブジェクトがapplicationContext.getResource()メソッドの呼び出しなどのファイルリソースにアクセスする必要がある場合、アプリケーションイベントapplicationContext.publishEvent(ApplicationEvent event)を公開する必要がある場合、またはMessageSourceにアクセスする必要がある場合、このメソッドは次のようになります。実装されました。ただし、これらの特定のシナリオでは、より具体的なResourceLoaderAware、ApplicationEventPublisherAware、またはMessageSourceAwareインターフェイスを実装することをお勧めします。
package org.springframework.context;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.Aware;
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
テストコードと単体テストの検証結果は次のとおりです。
package com.chenpi;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* @author 陈皮
* @version 1.0
* @description
* @date 2022/4/3
*/
@Component
public class Person implements BeanNameAware, BeanFactoryAware, ApplicationContextAware {
private String beanName;
private BeanFactory beanFactory;
private ApplicationContext applicationContext;
@Override
public void setBeanName(String name) {
this.beanName = name;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public String getBeanName() {
return beanName;
}
public BeanFactory getBeanFactory() {
return beanFactory;
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
}
package com.chenpi;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
@SpringBootTest
class ApplicationTests {
@Autowired
private Person person;
@Test
public void testValue() {
System.out.println("Person BeanName:" + person.getBeanName());
System.out.println("Person Bean's BeanFactory:" + person.getBeanFactory().getClass());
System.out.println(
person == person.getBeanFactory().getBean(person.getBeanName(), Person.class));
ApplicationContext applicationContext = person.getApplicationContext();
Person person1 = applicationContext.getBean(person.getBeanName(), Person.class);
System.out.println(applicationContext.getClass());
System.out.println(person == person1);
}
}
// 输出结果如下
Person BeanName:person
Person Bean's BeanFactory:class org.springframework.beans.factory.support.DefaultListableBeanFactory
true
class org.springframework.web.context.support.GenericWebApplicationContext
true