笔记参考B站黑马程序员视频:spring原理
1.Aware 接口
在 Spring Framework 中,Aware 接口用于使 bean 能够获取与容器相关的特定信息或服务。用于注入一些与容器相关信息,例如
- BeanNameAware 注入 bean 的名字
- BeanFactoryAware 注入 BeanFactory 容器
- ApplicationContextAware 注入 ApplicationContext 容器
- EmbeddedValueResolverAware ${}
BeanNameAware
作用:使 bean 能够获取自身在容器中配置的名字。
实现方式:实现 BeanNameAware 接口并重写 setBeanName(String name) 方法,Spring 容器在创建 bean 并设置完属性后会自动调用此方法,传入 bean 的名字。
package com.dreams.demo06;
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);
@Override
public void setBeanName(String name) {
log.debug("当前bean " + this + " 名字叫:" + name);
}
}启动类
package com.dreams.demo06;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.GenericApplicationContext;
/*
Aware 接口及 InitializingBean 接口
*/
public class DemoApplication {
private static final Logger log = LoggerFactory.getLogger(DemoApplication.class);
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("myBean", MyBean.class);
context.refresh();
context.close();
}
}
ApplicationContextAware
作用:使 bean 能够获取它所在的 ApplicationContext,即 Spring 应用上下文。
实现方式:实现 ApplicationContextAware 接口并重写 setApplicationContext(ApplicationContext applicationContext) 方法,Spring 容器在创建 bean 后会自动调用此方法,传入所在的 ApplicationContext 对象。
package com.dreams.demo06;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class MyBean implements BeanNameAware , ApplicationContextAware {
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);
}
}输出的就是我们的context对象

BeanFactoryAware
作用:使 bean 能够获取它所在的 BeanFactory,即 Spring 容器本身。
实现方式:实现 BeanFactoryAware 接口并重写 setBeanFactory(BeanFactory beanFactory) 方法,Spring 容器在创建 bean 后会自动调用此方法,传入所在的 BeanFactory 对象。
EnvironmentAware
作用:使 bean 能够获取 Spring 运行时环境的配置信息。
实现方式:实现 EnvironmentAware 接口并重写 setEnvironment(Environment environment) 方法,Spring 容器在创建 bean 后会自动调用此方法,传入运行时的 Environment 对象。
2.InitializingBean
InitializingBean 是 Spring Framework 提供的一个初始化回调接口,允许 bean 在初始化阶段执行特定的自定义逻辑。当 bean 实现了 InitializingBean 接口后,Spring 容器在完成 bean 的属性设置之后,会调用其 afterPropertiesSet() 方法,以便让 bean 执行额外的初始化操作。
package com.dreams.demo06;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
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 + " 初始化");
}
}
3.Aware 接口与@Autowired比较
@Autowired 的解析需要用到 bean 后处理器, 属于扩展功能,而 Aware 接口属于内置功能, 不加任何扩展, Spring 就能识别,某些情况下, 扩展功能会失效,而内置功能不会失效
比如以下情况,Aware 注入 ApplicationContext 成功, 而 @Autowired 注入 ApplicationContext 失败。
package com.dreams.demo06;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
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 初始化");
}
}可以看到@Autowired没有生效,因为GenericApplicationContext默认是没有添加处理器的。

回到启动类加入处理器就行
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("myBean", MyBean.class);
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
context.registerBean(CommonAnnotationBeanPostProcessor.class);
context.refresh();
context.close();
}
4.@Autowired失效
先看正常情况
package com.dreams.demo06;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@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("初始化");
}
}然后启动类加载它
package com.dreams.demo06;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
/*
Aware 接口及 InitializingBean 接口
*/
public class DemoApplication {
private static final Logger log = LoggerFactory.getLogger(DemoApplication.class);
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("myConfig1", MyConfig1.class);
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
context.registerBean(CommonAnnotationBeanPostProcessor.class);
context.registerBean(ConfigurationClassPostProcessor.class);
context.refresh();
context.close();
}
}这时是正常的

但是如果在Myconfig1中多加BeanFactoryPostProcessor配置
package com.dreams.demo06;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@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");
};
}
}可以看到BeanFactoryPostProcessor是正常注入了,但是其他全部失效了

对于context.refresh()方法,底层的流程是:
- beanFactory 后处理器
- 添加 bean 后处理器
- 初始化单例
Java 配置类不包含 BeanFactoryPostProcessor 的情况

Java 配置类包含 BeanFactoryPostProcessor 的情况,因此要创建其中的 BeanFactoryPostProcessor 必须提前创建 Java 配置类,而此时的 BeanPostProcessor 还未准备好,导致 @Autowired 等注解失效,后面轮到时配置类已经加载过了就不会重新加载了。

解决方法就是使用Aware 接口了
package com.dreams.demo06;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@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");
};
}
}
5.Bean初始化和销毁
初始化和销毁执行顺序
初始化Bean
package com.dreams.demo07;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import javax.annotation.PostConstruct;
public class Bean1 implements InitializingBean {
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
@PostConstruct
public void init1() {
log.debug("初始化1");
}
@Override
public void afterPropertiesSet() throws Exception {
log.debug("初始化2");
}
public void init3() {
log.debug("初始化3");
}
}销毁Bean
package com.dreams.demo07;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import javax.annotation.PreDestroy;
public class Bean2 implements DisposableBean {
private static final Logger log = LoggerFactory.getLogger(Bean2.class);
@PreDestroy
public void destroy1() {
log.debug("销毁1");
}
@Override
public void destroy() throws Exception {
log.debug("销毁2");
}
public void destroy3() {
log.debug("销毁3");
}
}启动类
package com.dreams.demo07;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
/*
初始化和销毁的执行顺序
*/
@SpringBootApplication
public class DemoApplication{
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
context.close();
}
@Bean(initMethod = "init3")
public Bean1 bean1() {
return new Bean1();
}
@Bean(destroyMethod = "destroy3")
public Bean2 bean2() {
return new Bean2();
}
}对应的执行顺序如下:

先依赖注入@Autowired -> Aware接口 -> 再初始化@PostContruct -> InitializingBean接口
6.参考
黑马程序员:spring


