- 使用 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 在一次求职面试中被要求编写一个程序来测量可用 RAM 的数量。预期的答案是以二进制搜索方式使用 malloc():分配越来越大的内存部分,直到收到失败消息,减少部分大小,然后对
我正在通过任务管理器检查 Chrome 中特定选项卡的内存消耗情况。它显示了我使用的 RAM 量相当大: 但是,当我在开发人员工具中拍摄堆快照时,其显示的大小要小几倍: 怎么会这样呢? 最佳答案 并非
是否有一种可移植的方式,可以在各种支持的操作系统上同时在 .Net 和 Mono 上运行,让程序知道它运行的机器上有多少 RAM(即物理内存而不是虚拟内存)可用? 上下文是一个程序,其内存要求是“请尽
有谁知道是否有办法查看 android studio 项目中的所有 View 、LinearLayout、TextView 等? 我正在使用 android 设备监视器中的层次结构查看器使用 xml
很简单,我想从 Python 脚本中运行外部命令/程序,完成后我还想知道它消耗了多少 CPU 时间。 困难模式:并行运行多个命令不会导致 CPU 消耗结果不准确。 最佳答案 在 UNIX 上: (a)
我需要在给定数组索引和范围的情况下,在返回新索引的数组中向前循环 X 量并向后循环 X 量。 如果循环向前到达数组的末尾,它将在数组的开头继续。如果循环在向后时到达开头,它会在数组末尾继续。 例如,数
Android 应用程序中是否有类似最大 Activity 的内容?我想知道,因为我正在考虑创建具有铃声功能的声音应用程序。它将有大约 40 个 Activity 。但只有 1 个会持续运行。那太多了
有什么方法可以限制这种演示文稿的 curl 量吗?我知道系统会根据我们以 taht 方式模态呈现的 viewcontroller View 内的内容自动 curl 。 但 thta 在我的 iPad
我正在编写一个 Java 应用程序,它需要检查系统中可用的最大 RAM 量(不是 VM 可用的 RAM)。有没有可移植的方式来做到这一点? 非常感谢:-) 最佳答案 JMX 您可以访问 java.la
我发现它使用了 600 MB 的 RAM,甚至超过了 Visual Studio(当它达到 400 MB 的 RAM 时我将其关闭)。 最佳答案 dart 编辑器基于 Eclipse,而 Eclips
这个问题已经有答案了: Java get available memory (10 个回答) 已关闭 7 年前。 假设我有一个专门运行一个程序的 JVM,我如何获得分配给 JVM 的 RAM 量? 假
我刚刚使用 Eclipse 编写了一个程序,该程序需要很长时间才能执行。它花费的时间甚至更长,因为它只将我的 CPU 加载到 25%(我假设这是因为我使用的是四核,而程序只使用一个核心)。有没有办法让
我编写了一个 2x2x2 魔方求解器,它使用广度优先搜索算法求解用户输入的立方体位置。该程序确实解决了立方体。然而,当我进入一个很难解决的问题时,我会在搜索的深处发现这个问题,我用完了堆空间。我的电脑
我正在尝试同步运行多个 fio 线程,但随着线程数量的增加,我的计算机内存不足。似乎每个 fio 线程占用大约 200MB 的 RAM。话虽这么说,有没有办法让每个线程都有一个固定的最大内存使用量?设
我使用“fitctree”函数(链接:https://de.mathworks.com/help/stats/classificationtree-class.html)在 Matlab 中开发了一个
我有一个 .NET 进程,由于我不会深入探讨的原因,它消耗了大量 RAM。我想要做的是对该进程可以使用的 RAM 量实现上限。有办法做到这一点吗? 我找到的最接近的是 Process.GetCurre
您可能已经看到许多“系统信息”应用程序,它们显示诸如剩余电池生命周期之类的信息,甚至显示内存等系统信息。 以类似的方式,是否有任何方法可以从我的应用中检索当前可用 RAM 量,以便我可以更好地决定何时
我从来都不是 MFC 的忠实粉丝,但这并不是重点。我读到微软将在 2010 年发布新版本的 MFC,这让我感到很奇怪 - 我以为 MFC 已经死了(不是恶意,我真的这样做了)。 MFC 是否用于新开发
我在一台安装了 8 GB 内存的机器上工作,我试图以编程方式确定机器中安装了多少内存。我已经尝试使用 sysctlbyname() 来获取安装的内存量,但它似乎仅限于返回带符号的 32 位整数。 ui
基本上,我想要一个由大小相同的 div(例如 100x100)和类似 200x100 的变体构建的页面。它们都 float :向左调整以相应地调整窗口大小。问题是,我不知道如何让它们在那种情况下居中,
我是一名优秀的程序员,十分优秀!