Aware 接口及 InitializingBean 接口

Aware接口作用

Aware 接口用于注入一些与容器相关信息
  1. BeanNameAware 注入 bean 的名字
  1. BeanFactoryAware 注入 BeanFactory 容器
  1. ApplicationContextAware 注入 ApplicationContext 容器
  1. EmbeddedValueResolverAware ${}
 
案例
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 " + this + " 名字叫:" + name); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { log.debug("当前bean " + this + " 容器是:" + applicationContext); } @Override public void afterPropertiesSet() throws Exception { log.debug("当前bean " + this + " 初始化"); } @Autowired public void aaa(ApplicationContext applicationContext) { log.debug("当前bean " + this + " 使用@Autowired 容器是:" + applicationContext); } @PostConstruct public void init() { log.debug("当前bean " + this + " 使用@PostConstruct 初始化"); } }
 
 
 
注册MyBean
public class A06 { private static final Logger log = LoggerFactory.getLogger(A06.class); public static void main(String[] args) { /* 1. Aware 接口用于注入一些与容器相关信息, 例如 a. BeanNameAware 注入 bean 的名字 b. BeanFactoryAware 注入 BeanFactory 容器 c. ApplicationContextAware 注入 ApplicationContext 容器 d. EmbeddedValueResolverAware ${} */ GenericApplicationContext context = new GenericApplicationContext(); context.registerBean("myBean", MyBean.class); context.registerBean(AutowiredAnnotationBeanPostProcessor.class); context.registerBean(CommonAnnotationBeanPostProcessor.class); context.registerBean(ConfigurationClassPostProcessor.class); context.refresh(); // 1. beanFactory 后处理器, 2. 添加 bean 后处理器, 3. 初始化单例 context.close(); } }
 
[INFO ] 10:03:41.050 [main] o.s.c.a.ConfigurationClassEnhancer - @Bean method MyConfig1.processor1 is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details. [DEBUG] 10:03:41.062 [main] com.onethink.a06.MyConfig1 - 执行 processor1 [DEBUG] 10:03:41.099 [main] com.onethink.a06.MyBean - 当前bean com.onethink.a06.MyBean@23f5b5dc 使用@Autowired 容器是:org.springframework.context.support.GenericApplicationContext@de3a06f, started on Sun Apr 02 10:03:40 CST 2023 [DEBUG] 10:03:41.099 [main] com.onethink.a06.MyBean - 当前bean com.onethink.a06.MyBean@23f5b5dc 名字叫:myBean [DEBUG] 10:03:41.099 [main] com.onethink.a06.MyBean - 当前bean com.onethink.a06.MyBean@23f5b5dc 容器是:org.springframework.context.support.GenericApplicationContext@de3a06f, started on Sun Apr 02 10:03:40 CST 2023 [DEBUG] 10:03:41.101 [main] com.onethink.a06.MyBean - 当前bean com.onethink.a06.MyBean@23f5b5dc 使用@PostConstruct 初始化 [DEBUG] 10:03:41.101 [main] com.onethink.a06.MyBean - 当前bean com.onethink.a06.MyBean@23f5b5dc 初始化

和@Autowired 的区别

  1. @Autowired 的解析需要用到 bean 后处理器, 属于扩展功能
  1. 而 Aware 接口属于内置功能, 不加任何扩展, Spring 就能识别某些情况下, 扩展功能会失效, 而内置功能不会失效

@Autowired 注入失效

例1: Aware 注入 ApplicationContext 成功, 而 @Autowired 注入 ApplicationContext 失败
@Configuration public class MyConfig1 { private static final Logger log = LoggerFactory.getLogger(MyConfig1.class); @Autowired public void setApplicationContext(ApplicationContext applicationContext) { log.debug("注入 ApplicationContext"); } @PostConstruct public void init() { log.debug("初始化"); } }
notion image
在配置类里初始化一个BeanFactoryPostProcessor对象
@Configuration public class MyConfig1 { private static final Logger log = LoggerFactory.getLogger(MyConfig1.class); @Autowired public void setApplicationContext(ApplicationContext applicationContext) { log.debug("注入 ApplicationContext"); } @PostConstruct public void init() { log.debug("初始化"); } @Bean // beanFactory 后处理器 public BeanFactoryPostProcessor processor1() { return beanFactory -> { log.debug("执行 processor1"); }; } }

配置类 @Autowired 失效分析

context.refresh()的作用
  1. beanFactory 后处理器
  1. 添加 bean 后处理器
  1. 初始化单例
 
Java 配置类不包含 BeanFactoryPostProcessor 的情况
sequenceDiagram participant ac as ApplicationContext participant bfpp as BeanFactoryPostProcessor participant bpp as BeanPostProcessor participant config as Java配置类 ac ->> bfpp : 1. 执行 BeanFactoryPostProcessor ac ->> bpp : 2. 注册 BeanPostProcessor ac ->> +config : 3. 创建和初始化 bpp ->> config : 3.1 依赖注入扩展(如 @Value 和 @Autowired) bpp ->> config : 3.2 初始化扩展(如 @PostConstruct) ac ->> config : 3.3 执行 Aware 及 InitializingBean config -->> -ac : 3.4 创建成功
Java 配置类包含 BeanFactoryPostProcessor 的情况,
要创建其中的 BeanFactoryPostProcessor 必须提前创建 Java 配置类,而此时的 BeanPostProcessor 还未准备好,导致 @Autowired 等注解失效
sequenceDiagram participant ac as ApplicationContext participant bfpp as BeanFactoryPostProcessor participant bpp as BeanPostProcessor participant config as Java配置类 ac ->> +config : 3. 创建和初始化 ac ->> config : 3.1 执行 Aware 及 InitializingBean config -->> -ac : 3.2 创建成功 ac ->> bfpp : 1. 执行 BeanFactoryPostProcessor ac ->> bpp : 2. 注册 BeanPostProcessor
 
解决方法:
  • 用内置依赖注入和初始化取代扩展依赖注入和初始化
  • 用静态工厂方法代替实例工厂方法,避免工厂对象提前被创建
 
@Configuration public class MyConfig2 implements InitializingBean, ApplicationContextAware { private static final Logger log = LoggerFactory.getLogger(MyConfig2.class); @Override public void afterPropertiesSet() throws Exception { log.debug("初始化"); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { log.debug("注入 ApplicationContext"); } @Bean // beanFactory 后处理器 public BeanFactoryPostProcessor processor2() { return beanFactory -> { log.debug("执行 processor2"); }; } }
 
public class A06 { private static final Logger log = LoggerFactory.getLogger(A06.class); public static void main(String[] args) { /* 1. Aware 接口用于注入一些与容器相关信息, 例如 a. BeanNameAware 注入 bean 的名字 b. BeanFactoryAware 注入 BeanFactory 容器 c. ApplicationContextAware 注入 ApplicationContext 容器 d. EmbeddedValueResolverAware ${} */ GenericApplicationContext context = new GenericApplicationContext(); // context.registerBean("myConfig1", MyConfig1.class); context.registerBean("myConfig2", MyConfig2.class); context.registerBean(AutowiredAnnotationBeanPostProcessor.class); context.registerBean(CommonAnnotationBeanPostProcessor.class); context.registerBean(ConfigurationClassPostProcessor.class); context.refresh(); // 1. beanFactory 后处理器, 2. 添加 bean 后处理器, 3. 初始化单例 context.close(); } }
notion image