- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
本文分享自华为云社区《有感知的 Aware Spring Bean》,作者:陈皮的JavaLib。
正常情况下,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 的方法。
注意,仅实现 Aware 接口不会提供默认功能。我们一般是实现 Aware 的子接口来获得特定的感知能力。
Aware 接口的子接口有很多,例如 BeanNameAware,BeanFactoryAware,ApplicationContextAware,EnvironmentAware,ApplicationEventPublisherAware 等等,以下介绍几个常用的用法。
如果 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
如果 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
如果 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
《新程序员》:云原生和全面数字化实践
50位技术专家共同创作,文字、视频、音频交互阅读
我会说服我的 friend ,在开发数据库应用程序时,在 Delphi 中使用数据库组件(DB Aware Controls)是迄今为止最好的选择。 这个争论从他很多年前就开始了:直到今天,他仍然相信
在谷歌 Awareness API 指南页面上,提到了上下文类型。 Contextual data includes sensor-derived data such as location (lat
我有一些用 Delphi 编写的业务对象,带有自定义的数据库持久性方案,最终满足了我的需求。太好了。现在是 GUI 实现的时候了。问题就从这里开始了。 如何将我的对象正确绑定(bind)到 GUI?
您如何在Hadoop中定义“机架感知”? 最佳答案 似乎机架感知意味着组件实际上可以区分托管在其上的物理机架服务器。如果您有兴趣,链接会更深入。 https://hadoop.apache.org/d
我很好奇我们许多从事设计或做出设计决策的人是否听说过这个问题。 我知道存在危险的颜色组合,例如绿色 + 红色。这可能是最常见的色盲案例之一。如果红色背景上有绿色文本,反之亦然,有些人将看不到任何内容。
我希望能够在我的 Android 应用程序中查看天气。我实现了它,但它似乎总是在返回条件:[2] 而不是别的,尽管这里已经下了将近一个小时的雨了。 这是它返回的内容: Temp=67.0F/19.44
我正在尝试在多个 session 中使用 Android 感知 API 注册多个位置围栏。但是每次我注册一个新的位置围栏时,它似乎会丢弃我的旧位置围栏并且不再触发它们。 String uniqueId
我认为标题说明了一切......但为了完整起见,这里是完整的问题。 问题 因此,我在 Visual Basic/C#/Anything.net 中有一个包含 Cell 实例的 2 列数组(矩阵或“网格
我想查看全新的 Awareness API。我正在使用 Play Services 9.0.2。文档有 this example : GoogleApiClient client = new Goog
我正在尝试找出一种在线算法,用于“时间感知”指数移动平均线,在不同时间进行采样。通过“时间感知”,我的意思是“给予在一天中相似时间采样的数据更多的权重”,但是(a)我将给出更精确的定义,并且(b)这只
在Struts2拦截器包中,我们可以看到很多XXXAware接口(interface),比如ApplicationAware、CookieAware等。 在Spring框架中,ApplicationC
我正在与 Java 团队一起使用 JavaFX WebView 开发 HTML+CSS+Javascript渲染器。我也想在普通浏览器中使用相同的 HTML+CSS+Javascript,但我希望在样
本文分享自华为云社区《有感知的 Aware Spring Bean》,作者:陈皮的JavaLib。 有感知能力的 Spring Bean 正常情况下,Spring 中的 Bean 对 Spring 是
我有一个带有 openocd 和 arm-none-eabi-gdb 的设置,我正在尝试调试 FreeRTOS fw。 我用以下命令启动 openocd: openocd -f /usr/local/
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
遵循 official documentation 中的指南,我尝试使用以下语句将 Awareness API 添加为我的应用程序的依赖项: compile "com.google.android.g
我在手机上使用较低版本 (9.4.0) 的相同代码,但出于某种原因它不能在 RPi3 上运行?我的构建.gradle compile 'com.google.android.gms:play-serv
好吧,我正在测试如何编写一个 C++ 应用程序,它实际上可以读取(和更改)文本文件,同时遵守用于文本的编码。我希望(对于其他 API)将所有读取的文本显式转换为 UTF-8 以供内部使用。与文件中的实
我正在使用 Genesis LifeStyle Pro 子主题。网址:https://www.test.rainerklar.de/blog-fuer-verjuengung-und-gesundhe
我有一个关于在 C++ 中向 std::map 插入内容的问题。 这就是我的代码: stringutils.hh: ... unsigned long hashSDBM(char *strToHa
我是一名优秀的程序员,十分优秀!