第六讲-Aware接口和InitializingBean接口
第六讲-Aware接口和InitializingBean接口
Aware接口的作用是注入一些与容器相关的信息
- BeanNameAware注入bean的名字
- BeanFactoryAware注入到BeanFaactory容器
- ApplicationContextAware注入到ApplicationContext容器中
- 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接口呢?简单来说,有如下两个原因:
- @Autowired注解的解析需要使用Bean后处理器,这是属于Spring Bean的扩展功能
- 而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后处理器就生效了!
分类:
Spring 高级49讲
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .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语句:使用策略模式优化代码结构