第六讲-Aware接口和InitializingBean接口

第六讲-Aware接口和InitializingBean接口

Aware接口的作用是注入一些与容器相关的信息

  1. BeanNameAware注入bean的名字
  2. BeanFactoryAware注入到BeanFaactory容器
  3. ApplicationContextAware注入到ApplicationContext容器中
  4. EmbeddedValueResolverAware注入到${}

而InitializingBean接口是帮助我们为Bean添加初始化方法的。

举个例子,编写一个Bean,实现BeanNameAware接口

package com.cherry.chapter1.a06;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanNameAware;

public class MyBean implements BeanNameAware {

    private static final Logger log = LoggerFactory.getLogger(MyBean.class);

    // 将来MyBean1在创建过程中(初始化之前)就会调用接口中的方法
    @Override
    public void setBeanName(String name) {
        log.debug("当前bean名字叫:{}",name);
        log.debug("当前bean:{}",this);

    }
}

在主方法中创建容器并启动测试:

package com.cherry.chapter1.a06;

import org.springframework.context.support.GenericApplicationContext;

public class A06Application {
    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("myBean", MyBean.class);
        context.refresh();
        context.close();
    }
}
13:08:18.413 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前bean名字叫:myBean
13:08:18.415 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前bean:com.cherry.chapter1.a06.MyBean@147ed70f

同样的,实现ApplicationContextAware接口也可以获取当前Bean所在的容器:

// 将来MyBean1在创建过程中(初始化之前)就会调用接口中的方法
public class MyBean implements BeanNameAware, ApplicationContextAware {

    private static final Logger log = LoggerFactory.getLogger(MyBean.class);

    @Override
    public void setBeanName(String name) {
        log.debug("当前bean名字叫:{}",name);
        log.debug("当前bean:{}",this);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.debug("当前bean所在的容器是:{}", applicationContext);
    }
}
13:11:05.432 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前bean名字叫:myBean
13:11:05.435 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前bean:com.cherry.chapter1.a06.MyBean@cb644e
13:11:05.435 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前bean所在的容器是:org.springframework.context.support.GenericApplicationContext@3b22cdd0, started on Wed Jul 24 13:11:05 CST 2024
13:11:05.501 [main] DEBUG org.springframework.context.support.GenericApplicationContext

同样的,实现InitializingBean接口来完成真正的Bean初始化工作:

// 将来MyBean1在创建过程中(初始化之前)就会调用接口中的方法
public class MyBean implements BeanNameAware, ApplicationContextAware, InitializingBean {

    private static final Logger log = LoggerFactory.getLogger(MyBean.class);

    @Override
    public void setBeanName(String name) {
        log.debug("当前bean名字叫:{}",name);
        log.debug("当前bean:{}",this);

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.debug("当前bean所在的容器是:{}", applicationContext);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.debug("当前bean"+this+"初始化");
    }
}
13:15:09.004 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前bean名字叫:myBean
13:15:09.006 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前bean:com.cherry.chapter1.a06.MyBean@56ef9176
13:15:09.007 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前bean所在的容器是:org.springframework.context.support.GenericApplicationContext@3b22cdd0, started on Wed Jul 24 13:15:08 CST 2024
13:15:09.011 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前beancom.cherry.chapter1.a06.MyBean@56ef9176初始化

这时有人就问了,上面的功能同样也可以使用@Autowired注解实现呀,为啥还要使用@Aware接口呢?简单来说,有如下两个原因:

  1. @Autowired注解的解析需要使用Bean后处理器,这是属于Spring Bean的扩展功能
  2. 而Aware接口属于Spring内置的功能,该接口不会加入任何扩展,Spring就能识别得到,因为在某些情况下,扩展功能会失效,而内置功能则不会失效。例如,你使用Autowire接口注入ApplicationContext会成功,但是,使用@Autowired注入ApplicationContext就会失败。

如下面的例子,在Bean中添加如下代码:

@Autowired
public void aaa(ApplicationContext context){
    log.debug("当前bean{}使用@Autowired注解注入,容器为:{}",this, context);
}

@PostConstruct
public void init(){
    log.debug("当前bean:{}使用@PostConstruct初始化",this);
}

测试如下:

18:20:03.196 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前bean名字叫:myBean
18:20:03.198 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前bean:com.cherry.chapter1.a06.MyBean@56ef9176
18:20:03.198 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前bean所在的容器是:org.springframework.context.support.GenericApplicationContext@3b22cdd0, started on Wed Jul 24 18:20:03 CST 2024
18:20:03.201 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前beancom.cherry.chapter1.a06.MyBean@56ef9176初始化

我们发现,此时的注入失效了,我们要想生效,就要加入相应的Bean后处理器才可以生效!

例如我们添加如下的后处理器,再次运行:

context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
context.registerBean(CommonAnnotationBeanPostProcessor.class);
18:27:06.688 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前beancom.cherry.chapter1.a06.MyBean@4eb7f003使用@Autowired注解注入,容器为:org.springframework.context.support.GenericApplicationContext@3b22cdd0, started on Wed Jul 24 18:27:06 CST 2024
18:27:06.695 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前bean名字叫:myBean
18:27:06.695 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前bean:com.cherry.chapter1.a06.MyBean@4eb7f003
18:27:06.695 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前bean所在的容器是:org.springframework.context.support.GenericApplicationContext@3b22cdd0, started on Wed Jul 24 18:27:06 CST 2024
18:27:06.696 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前bean:com.cherry.chapter1.a06.MyBean@4eb7f003使用@PostConstruct初始化
18:27:06.696 [main] DEBUG com.cherry.chapter1.a06.MyBean - 当前beancom.cherry.chapter1.a06.MyBean@4eb7f003初始化

我们发现,加入相关的Bean后处理器就生效了!

posted @   LilyFlower  阅读(7)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示