一緒に書く習慣を身につけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加して3日目です。クリックしてイベントの詳細をご覧ください。
春の豆を意識する
通常の状況では、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のサブインターフェイスを実装します。
Aware 接口的子接口有很多,例如 BeanNameAware,BeanFactoryAware,ApplicationContextAware,EnvironmentAware,ApplicationEventPublisherAware 等等,以下介绍几个常用的用法。
BeanNameAware 接口
如果 bean 需要知道自己在 bean 工厂中的 beanName,即在 Spring 容器中的名字(标识)。可以实现此 BeanNameAware 接口。BeanNameAware 接口源码如下,只有一个方法,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 对象,进行协作。当然也不推荐这种方式,推荐使用 DI 方式注入依赖的 bean 对象。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 接口。可以通过 Spring 容器获取其他 Bean 对象,进行协作。
もちろん、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
复制代码
この共有はここで終了します~~
私はインターネットコーディングのITerであるChenPiです。お気に入り、フォロー、コメントなど、記事があなたに役立つと思うなら、あなたのサポートが私の作成の最大の動機です!