首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Spring揭秘:ApplicationContextAware应用场景及实现原理!

Spring揭秘:ImportBeanDefinitionRegistrar应用场景及实现原理! - 程序员古德内容概要

ApplicationContextAware接口能够轻松感知并在Spring中获取应用上下文,进而访问容器中的其他Bean和资源,这增强了组件间的解耦,了代码的灵活性和可扩展性,是Spring框架中实现高级功能的关键接口之一。

核心概念

它能用来干啥?

为了方便理解,模拟一个业务场景。假如有一个功能模块负责处理订单,在这个模块中,有一个OrderService类,它负责订单的创建、更新和查询等操作,单在处理订单的过程中,可能需要访问其他一些服务,比如用户服务来获取用户信息,或者库存服务来检查商品库存。

在这个场景中,可以使用ApplicationContextAware接口来解决,可以创建一个类,比如叫OrderServiceContextAware,让它实现ApplicationContextAware接口,当Spring容器初始化这个类时,它会自动将应用上下文注入到这个类中,一旦注入了应用上下文,OrderServiceContextAware就能够访问到容器中的其他Bean,包括用户服务和库存服务。

可以在OrderService类中使用OrderServiceContextAware来获取用户服务和库存服务的实例,而无需直接在OrderService中注入这些服务,这样OrderService类不直接依赖于其他服务的具体实现,而是通过OrderServiceContextAware来间接访问这些服务。

它有哪些特性?

ApplicationContextAware是Spring框架提供的一个特殊的回调接口,用于帮助对象(特别是普通的Java Bean)访问到Spring的应用上下文ApplicationContext。

当在自己的类中实现ApplicationContextAware接口时,可以通过Spring提供的回调机制访问到Spring的应用上下文,从而获得Spring IoC容器中的bean实例、配置信息以及进行国际化操作、事件发布等操作。

在ApplicationContextAware接口中定义了一个setApplicationContext方法,当类实现了该接口之后,Spring IoC容器会自动调用该方法并将当前的ApplicationContext注入到所实现的setApplicationContext方法中,这样就可以在该类中使用Spring的应用上下文了。

在一些开源的Spring工具库中会看到这种技术的使用,因为这些库往往需要与Spring容器交互,比如读取容器的配置,访问其他的bean等等,通过实现ApplicationContextAware接口就可以非常方便地完成这些工作。

但注意,一般不推荐在的业务代码中使用,因为这样会增加代码与Spring的耦合性,违反了“依赖于抽象,而非依赖于具体实现”的面向对象设计原则。业务代码应当尽可能减少对具体框架的依赖,以提高代码的通用性和可移植性。

代码案例

下面是一个简单的代码案例,展示了如何使用ApplicationContextAware接口来创建一个能够访问Spring应用上下文的类,如下代码:

首先,创建一个实现ApplicationContextAware接口的类:

import org.springframework.beans.BeansException;

import org.springframework.context.ApplicationContext;

import org.springframework.context.ApplicationContextAware;

import org.springframework.stereotype.Component;

@Component

public class SpringContextUtil implements ApplicationContextAware {

// Spring应用上下文

private static ApplicationContext applicationContext;

// 当Spring容器创建该类的实例时,会自动调用此方法,注入应用上下文

@Override

public void setApplicationContext(ApplicationContext context) throws BeansException {

SpringContextUtil.applicationContext = context;

}

// 提供一个静态方法,返回应用上下文

public static ApplicationContext getApplicationContext() {

return applicationContext;

}

// 提供一个获取Bean的静态方法

public static <T> T getBean(Class<T> beanClass) {

if (applicationContext != null) {

return applicationContext.getBean(beanClass);

} else {

throw new IllegalStateException("ApplicationContext is not initialized yet!");

}

}

}

接着,定义一个简单的服务类作为Spring Bean:

然后,可以使用Spring的Java配置或者XML配置来定义和初始化这些Bean,假设使用Java配置:

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

public class AppConfig {

@Bean

public SpringContextUtil springContextUtil() {

return new SpringContextUtil();

}

@Bean

public DemoService demoService() {

return new DemoService();

}

}

最后,在客户端代码中,我们可以通过SpringContextUtil类来获取DemoService的实例并调用其方法:

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ApplicationClient {

public static void main(String[] args) {

// 创建Spring上下文,注册Java配置类

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

// 关闭Spring上下文,以便能够正常结束程序(尽管在这个示例中可能不需要)

context.registerShutdownHook();

// 通过SpringContextUtil获取DemoService实例

DemoService demoService = SpringContextUtil.getBean(DemoService.class);

// 调用DemoService的sayHello方法

System.out.println(demoService.sayHello());

}

}

输出结果:

复制代码

Hello from DemoService!

以上代码展示了如何通过SpringContextUtil访问Spring的应用上下文,并获取其中的一个bean(DemoService)。

ApplicationClient类是客户端代码的入口点,它初始化了一个AnnotationConfigApplicationContext,通过它Spring可以创建和管理beans,随后客户端代码使用SpringContextUtil.getBean静态方法来获取DemoService的实例,并调用它的sayHello方法。

核心API

ApplicationContextAware接口是一个特殊的标记接口。

它允许实现类能够访问到ApplicationContext,即Spring的应用上下文,ApplicationContextAware中有且只有一个核心方法,如下是该方法的说明:

public interface ApplicationContextAware extends Aware {

void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}

setApplicationContext方法的含义如下:

void setApplicationContext(ApplicationContext applicationContext) throws BeansException:这个方法会在Spring容器初始化的时候被自动调用,Spring容器会将当前的ApplicationContext作为参数传递给该方法,实现这个接口的类可以在这个方法中保存对ApplicationContext的引用,从而能够在后续的操作中使用这个上下文。

如下是实现ApplicationContextAware接口的类的代码案例,如下:

@Component

public class MyApplicationContextAware implements ApplicationContextAware {

private ApplicationContext applicationContext;

@Override

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

this.applicationContext = applicationContext;

}

public ApplicationContext getApplicationContext() {

return this.applicationContext;

}

}

技术原理

ApplicationContextAware接口是Spring框架中用于让Bean感知到Spring应用上下文ApplicationContext的存在的一个标记接口。

当Spring容器创建一个实现了ApplicationContextAware接口的Bean时,它会自动调用该Bean的setApplicationContext方法,并将当前的ApplicationContext作为参数传入,这使得Bean能够访问到Spring容器的上下文,进而可以获取容器中的其他Bean、资源、配置信息等。

实现原理

标记接口: ApplicationContextAware接口本身并没有定义任何具体的业务逻辑,它只是一个标记接口,用于告诉Spring容器这个Bean需要特殊处理。

容器回调: 当Spring容器初始化一个Bean时,如果这个Bean实现了ApplicationContextAware接口,Spring容器会调用该Bean的setApplicationContext方法,并将当前的ApplicationContext对象作为参数传入。

内部状态保存: 实现ApplicationContextAware接口的Bean通常会在其内部保存这个传入的ApplicationContext引用,以便后续使用。

使用上下文: 一旦Bean保存了ApplicationContext的引用,它就可以使用这个上下文来访问容器中的其他Bean,或者获取容器的其他服务。

工作机制

Bean创建: 当Spring容器根据配置信息创建一个Bean实例时,它会检查这个Bean是否实现了任何Aware接口(包括ApplicationContextAware)。

Aware接口处理: 如果Bean实现了Aware接口,Spring容器会调用相应的set*方法,注入相应的依赖,对于ApplicationContextAware,容器会调用setApplicationContext方法。

依赖注入: 在调用setApplicationContext方法时,Spring容器会将当前的ApplicationContext对象注入到Bean中,这个注入过程是通过Java反射机制实现的。

Bean后处理: 在Bean的所有属性被设置之后,Spring容器会调用Bean的后处理器(如果配置了的话),进行额外的初始化工作,对于实现了InitializingBean接口的Bean,还会调用其afterPropertiesSet方法。

使用ApplicationContext: 一旦Bean被初始化并注入了ApplicationContext,它就可以使用这个上下文来执行各种操作,比如获取其他Bean、访问资源、读取配置等。

核心总结

Spring揭秘:ApplicationContextAware应用场景及实现原理! - 程序员古德

ApplicationContextAware接口允许开发者在Bean中轻松获取到应用上下文ApplicationContext,这使得Bean能够灵活地访问Spring容器中的其他Bean和资源,增强了组件间的解耦和可扩展性。

但是,过度使用ApplicationContextAware可能导致代码与Spring容器紧密耦合,降低了代码的可移植性和可测试性。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OfCn0ClFK45ZbCvIrYQZ8DkA0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券