• Spring framework Day22:Aware接口


    前言

    Spring框架中,有许多接口和类都有一个非常重要的作用——让我们能够更方便地构建应用程序和管理组件。其中,Aware接口就是其中一个非常重要的接口之一。通过实现该接口,我们可以让Spring容器感知到特定的组件和资源,并进行初始化或注入。本文将介绍Aware接口的概念、使用方法以及示例。

    一、什么是 Aware 接口

    Aware接口是Spring框架中的一个非常重要的接口,它定义了一些回调方法,用于让Spring容器感知到特定的组件或资源。通过实现Aware接口,我们可以让Spring容器向特定的组件注入自己所持有的一些资源,或者让Spring容器调用特定的组件方法来对其进行初始化或其他操作。这样,我们就可以更方便地管理组件和资源,将它们更好地整合到Spring应用程序中。

    二、开始学习

    1、新建项目,结构如下

     2、添加 spring 依赖
    1. <dependencies>
    2. <dependency>
    3. <groupId>org.springframeworkgroupId>
    4. <artifactId>spring-contextartifactId>
    5. <version>5.3.23version>
    6. dependency>
    7. <dependency>
    8. <groupId>ch.qos.logbackgroupId>
    9. <artifactId>logback-classicartifactId>
    10. <version>1.4.5version>
    11. dependency>
    12. dependencies>
     3、在 service 包下新建一个 UserService 类
    1. @Slf4j
    2. @Service
    3. public class UserService implements BeanNameAware {
    4. /**
    5. * 注入 bean 的名字
    6. */
    7. private String beanName;
    8. /**
    9. * 容器会通过这个 set 方法将 bean 的名称注入进来
    10. *
    11. * @param beanName
    12. */
    13. @Override
    14. public void setBeanName(String beanName) {
    15. this.beanName = beanName;
    16. }
    17. public void add() {
    18. log.info("添加用户,使用 beanName:" + this.beanName);
    19. }
    20. }

    BeanNameAware是一个Spring框架提供的接口,实现该接口可以让类获取到自己在容器中的名称。在这个示例中,UserService实现了BeanNameAware接口,通过重写其中的setBeanName()方法,获取了自身在容器中的名称,并保存在了beanName字段中。

    这个字段虽然看似没有实际作用,但在某些场景下是比较有用的。例如,在项目中可能存在多个名字不同但功能相同的类,使用beanName字段就可以区分它们。又或者,在将来需要对某种类型的Bean进行特殊的处理时,也可以根据beanName来进行判断和操作。

    同时,@Slf4j注解是Lombok库提供的注解,可以自动生成log对象,使用log.info()等方法输出日志信息。在这个示例中,UserService类中的add()方法使用了log.info()输出了一条包含beanName字段的日志信息。

    综合起来看,这段代码中的BeanNameAware@Slf4j注解,虽然看似没有实际作用,但还是提供了一些便利和可扩展性。

    Aware 接口(感知型接口),当 spring 容器发现某个 bean,实现了 Aware 接口以后,name 就会为这个 bean 注入一些容器核心对象,比如某些业务场景中需要得到 bean 的名字或者 id 时,可以通过此接口来获取。

    4、 在 config 包下新建一个 AppConfig 类和 ApplicationContextHolder 工具类

    AppConfig 类

    1. @Configuration
    2. @ComponentScan(basePackages = "edu.nf.ch22")
    3. public class AppConfig {
    4. }

    AppConfig是一个配置类,使用了@Configuration注解来标识它是一个配置类。配置类主要用于定义和配置应用程序中的Bean,通常与Spring的IoC容器一起使用。

    @ComponentScan注解是用来指定扫描组件的基础包路径的。在这个示例中,basePackages属性指定了需要扫描的基础包路径为edu.nf.ch22。这意味着Spring容器会扫描该路径下的所有类,并将符合条件的类注册为Bean。

    通过@ComponentScan注解,Spring会自动扫描并创建被@Component@Service@Repository@Controller等注解修饰的类的实例,并将其纳入IoC容器进行管理。

    ApplicationContextHolder 工具类

    1. public class ApplicationContextHolder implements ApplicationContextAware {
    2. /**
    3. * 声明容器
    4. */
    5. private static ApplicationContext applicationContext;
    6. /**
    7. * 通过 set 方法将容器本身给注入进来
    8. *
    9. * @param appContext
    10. * @throws BeansException
    11. */
    12. @Override
    13. public void setApplicationContext(ApplicationContext appContext) throws BeansException {
    14. applicationContext = appContext;
    15. }
    16. public static ApplicationContext getApplicationContext() {
    17. return applicationContext;
    18. }
    19. /**
    20. * 封装了容器的 getBean 方法
    21. * @param id
    22. * @param clazz
    23. * @param
    24. * @return
    25. */
    26. public static T getBean(String id, Class clazz) {
    27. return applicationContext.getBean(id, clazz);
    28. }
    29. /**
    30. * 封装容器 getBean 方法
    31. * @param clazz
    32. * @param
    33. * @return
    34. */
    35. public static T getBean(Class clazz){
    36. return applicationContext.getBean(clazz);
    37. }
    38. }

     ApplicationContextHolder是一个实现了ApplicationContextAware接口的类,用于获取和管理Spring的应用上下文。

    首先,该类声明了一个静态的applicationContext字段,用于保存应用上下文对象。

    然后,通过实现setApplicationContext()方法,将应用上下文对象注入到applicationContext字段中。当Spring容器初始化时,会自动调用setApplicationContext()方法,并传入应用上下文对象。

    接下来,该类提供了两个静态方法:

    1. getApplicationContext():用于获取应用上下文对象,即返回保存在applicationContext字段中的对象。

    2. getBean():封装了应用上下文的getBean()方法,提供了两个重载版本。一个是根据id和Class类型获取Bean对象,另一个是根据Class类型获取Bean对象。这两个方法可以方便地在应用中获取被Spring管理的Bean对象。

    通过使用ApplicationContextHolder类,我们可以在任何地方获取到Spring的应用上下文对象,并使用其提供的方法获取需要的Bean对象,避免了在代码中手动获取或保持应用上下文对象的麻烦。这样可以更方便地管理和使用Spring容器中的组件。

     5、在 service 包下再建一个 StuService  类
    1. @Service
    2. @Slf4j
    3. public class StuService {
    4. public void add(){
    5. // 直接使用 ApplicationContextHolder
    6. UserService bean = ApplicationContextHolder.getBean("userService",UserService.class);
    7. bean.add();
    8. }
    9. }

    StuService类中,使用了ApplicationContextHolder来获取UserService的实例并调用其方法。

    首先,StuService类被标记为@Service注解,表示它是一个服务组件,会被Spring容器扫描并管理。

    add()方法中,通过ApplicationContextHolder.getBean()方法从应用上下文中获取名为"userService"的UserService实例,并将其赋值给bean变量。

    然后,调用bean.add()方法,即调用UserService实例的add()方法。

    通过使用ApplicationContextHolder.getBean()方法,我们可以在StuService中直接获取其他被Spring管理的Bean,而不需要依赖注入或手动创建对象。这样可以方便地在不同的组件之间进行交互和调用,提高代码的可维护性和灵活性。

     6、测试
    1. public class Main {
    2. public static void main(String[] args) {
    3. ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    4. UserService bean = context.getBean(UserService.class);
    5. bean.add();
    6. }
    7. }

    运行结果

     Aware 接口(感知型接口),当 spring 容器发现某个 bean,实现了 Aware 接口以后,name 就会为这个 bean 注入一些容器核心对象,比如某些业务场景中需要得到 bean 的名字或者 id 时,可以通过此接口来获取。

    三、使用 BeanNameAware、ApplicationContextAware 这两个接口的好处

    BeanNameAware 接口和 ApplicationContextAware 接口是 Spring Framework 提供的 Aware 接口之一,它们分别用于在 Bean 实例化和初始化过程中获取相关的信息和资源。它们的使用可以带来以下好处:

    1. BeanNameAware 接口的好处:

      • 获取当前 Bean 在容器中的名称:通过实现 BeanNameAware 接口,可以在 Bean 初始化阶段获得当前 Bean 在容器中的名称,这样在后续的操作中可以根据名称进行进一步的处理或判断。
    2. ApplicationContextAware 接口的好处:

      • 访问容器对象:通过实现 ApplicationContextAware 接口,可以在 Bean 初始化阶段获取到 Spring 容器的上下文对象(ApplicationContext),从而可以直接使用容器提供的各种功能,如获取其他 Bean、发布事件等。
      • 获取环境信息:ApplicationContext 接口继承了 EnvironmentCapable 接口,因此可以通过实现 ApplicationContextAware 接口来获取当前环境的相关信息,包括配置文件中的属性值、系统变量等。这样可以根据环境信息作出不同的处理逻辑。

    综上所述,BeanNameAware 和 ApplicationContextAware 接口的使用可以让你的 Bean 在实例化和初始化过程中获得更多的信息和资源,使其能够更好地适应和利用 Spring 容器的功能。通过这些接口,你可以在 Bean 中获取到容器中的其他 Bean、环境信息等,并根据这些信息进行相应的处理和操作,增加了代码的灵活性和可扩展性。然而,在使用这些 Aware 接口时,需要注意避免过度依赖容器的实现细节,保持代码的松耦合性,以便提高代码的可测试性和可维护性。

    四、gitee 案例

    案例完整地址:https://gitee.com/qiu-feng1/spring-framework.git

    
                    
  • 相关阅读:
    MySQL 主从复制与读写分离
    2.驱动安装
    python设计模式_Python六大原则,23种设计模式
    NB的Github项目,看到最后一个我惊呆了!
    OpenCV入门(C++/Python)- 使用OpenCV标注图像(六)
    Linux虚拟机中网络连接的三种方式
    携手并进 | 云畅科技与华商智造院签署战略合作协议
    致敬2023,人工智能(AI)一个技术飞速发展的2023
    togaf 知识点整理
    有 3 个候选人,每个选民只能投票选一人,要求编一个统计选票的程序,先后输入被选人的名字,最后输出各人得票结果
  • 原文地址:https://blog.csdn.net/zhiqiuqiu2/article/details/133908694