Spring 高级 Aware 接口及 InitializingBean 接口
一、Aware
1、Aware 接口的作用
Aware 接口提供了一种【内置】 的注入手段,例如
- BeanNameAware 注入 bean 的名字
- BeanFactoryAware 注入 BeanFactory 容器
- ApplicationContextAware 注入 ApplicationContext 容器
- EmbeddedValueResolverAware 注入 ${} 解析器
2、示范
package com.mangoubiubiu.show.a06; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanNameAware; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; /** * 在Bean创建过程中,初始化之前,就会回调BeanNameAware 接口 将Bean的名字传过来 */ @Slf4j public class MyBean implements BeanNameAware , ApplicationContextAware { @Override public void setBeanName(String s) { log.info("当前bean:{},名字叫{}",this,s); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { log.info("当前bean:{},容器是{}",this,applicationContext); } }
package com.mangoubiubiu.show.a06; import lombok.extern.slf4j.Slf4j; import org.springframework.context.support.GenericApplicationContext; @Slf4j public class A06Application { public static void main(String[] args) { /* Aware 接口提供了一种【内置】 的注入手段,例如 * BeanNameAware 注入 bean 的名字 * BeanFactoryAware 注入 BeanFactory 容器 * ApplicationContextAware 注入 ApplicationContext 容器 * EmbeddedValueResolverAware 注入 ${} 解析器 */ GenericApplicationContext context = new GenericApplicationContext(); context.registerBean("myBean",MyBean.class); context.refresh();//初始化容器 context.close();//关闭容器 } }
二、InitializingBean
1 InitializingBean 接口的作用
- InitializingBean 接口提供了一种【内置】的初始化手段
- 对比
- 内置的注入和初始化不受扩展功能的影响,总会被执行
- 而扩展功能受某些情况影响可能会失效
- 因此 Spring 框架内部的类常用内置注入和初始化
2、示范
package com.mangoubiubiu.show.a06; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; /** * 在Bean创建过程中,初始化之前,就会回调BeanNameAware 接口 将Bean的名字传过来 */ @Slf4j public class MyBean implements BeanNameAware , ApplicationContextAware, InitializingBean { @Override public void setBeanName(String s) { log.info("当前bean:{},名字叫{}",this,s); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { log.info("当前bean:{},容器是{}",this,applicationContext); } /** * 先去回调Bean的Aware 接口 然后再去执行的是InitializingBean的初始化方法 * @throws Exception */ @Override public void afterPropertiesSet() throws Exception { log.info("当前bean:{},初始化",this); } }
三、面试考点(重点!!!)
问题一:Aware 接口的以下功能都能用@Autowired就能实现,为啥还要用Aware 接口呢
- BeanFactoryAware 注入 BeanFactory 容器
- ApplicationContextAware 注入 ApplicationContext 容器
- EmbeddedValueResolverAware 注入 ${} 解析器
答:1、@Autiwired的解析需要用到bean后处理器,属于扩展功能。
2、而Aware 接口属于内置功能,不加任何扩展,Spring就能识别
某些情况下,扩展功能会失效,而内置功能不会失效
示范
package com.mangoubiubiu.show.a06; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import javax.annotation.PostConstruct; /** * 在Bean创建过程中,初始化之前,就会回调BeanNameAware 接口 将Bean的名字传过来 */ @Slf4j public class MyBean implements BeanNameAware , ApplicationContextAware, InitializingBean { @Override public void setBeanName(String s) { log.info("当前bean:{},名字叫{}",this,s); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { log.info("当前bean:{},容器是{}",this,applicationContext); } /** * 先去回调Bean的Aware 接口 然后再去执行的是InitializingBean的初始化方法 * @throws Exception */ @Override public void afterPropertiesSet() throws Exception { log.info("当前bean:{},初始化",this); } @Autowired public void addAutowired(ApplicationContext applicationContext){ log.info("使用 @Autowired 注入 当前bean:{},容器是{}",this,applicationContext); } @PostConstruct public void init(){ log.info("使用 @PostConstruct 当前bean:{},初始化",this); } }