感性を意識した春の豆

一緒に書く習慣を身につけましょう!「ナゲッツデイリーニュープラン・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より適切なインターフェイスを実装することをお勧めします。ApplicationEventPublisherAwareMessageSourceAware

 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です。お気に入り、フォロー、コメントなど、記事があなたに役立つと思うなら、あなたのサポートが私の作成の最大の動機です!

おすすめ

転載: juejin.im/post/7083494538089594888