Spring的xxxAware接口工作原理-笔记
1.Aware
接口的工作原理
Spring 提供了多个 XXXAware
接口(如 ApplicationEventPublisherAware
、ApplicationContextAware
、BeanFactoryAware
等),这些接口的核心作用是让 Bean 在初始化过程中自动获取特定的依赖。
- 实现
Aware
接口的 Bean:当 Spring 容器创建一个实现了Aware
接口的 Bean 时,容器会自动调用接口定义的setXXX
方法,传入对应的依赖对象。 - 无需
@Autowired
:Aware
接口的注入由 Spring 容器在 Bean 初始化阶段自动触发,不需要显式使用@Autowired
或构造函数注入。
2.Aware
赋值过程演示
以ApplicationEventPublisherAware
的赋值过程为例,演示Aware赋值过程。
步骤 1:创建UserService的bean
当Spring 容器初始化 UserService
(它实现了 ApplicationEventPublisherAware
)时,检测到UserService
实现了 ApplicationEventPublisherAware
接口,先执行步骤2.
@Service
public class UserService implements ApplicationEventPublisherAware {private ApplicationEventPublisher publisher;@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher publisher) {this.publisher = publisher; // 这里会被 Spring 自动调用}// 其他方法...
}
步骤 2:Spring 容器检测到 Aware
接口
Spring容器检测到 UserService
实现了 ApplicationEventPublisherAware
接口,因此会:
- 查找
ApplicationEventPublisher
的实现 Bean:Spring 容器会自动将ApplicationContext
作为ApplicationEventPublisher
的实现(ApplicationContext
是 Spring 容器的核心接口,它直接实现了ApplicationEventPublisher
接口。因此,Spring 容器会将ApplicationContext
自身作为ApplicationEventPublisher
的实现传入。)。 - 调用
setApplicationEventPublisher
方法:Spring容器自动调用setApplicationEventPublisher方法
将ApplicationContext
的实例赋值给publisher
变量。
步骤 3:初始化完成,生成bean
最终,publisher
变量被赋值为 ApplicationContext
的实例,UserService初始化完成,生成对应的bean
。
总结:
当Spring容器创建UserService这个Bean的时候,它检查到这个Bean实现了Aware接口,
Spring 容器自动调用 setApplicationEventPublisher
方法,将 ApplicationContext
的实例注入到 publisher
变量中。
在这个过程中,publisher变量的赋值是通过Spring容器在Bean初始化阶段自动完成的,不需要开发者手动使用@Autowired或者其他注解。
3.Aware方式 vs
@Autowired
两种注入方式用法
使用Aware方式 和 使用
@Autowired 引入bean的方式效果类似:
@Service
public class UserServiceWithAutowired {private final ApplicationEventPublisher publisher;@Autowiredpublic UserServiceWithAutowired(ApplicationEventPublisher publisher) {this.publisher = publisher;// 验证 publisher 是 ApplicationContext 的实例System.out.println("UserServiceWithAutowired.publisher class: " + publisher.getClass().getName()); //输出:UserServiceWithAutowired.publisher class: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext}//其他业务代码...
}
@Service
public class UserServiceWithAware implements ApplicationEventPublisherAware {private ApplicationEventPublisher publisher;/*** Aware 类会在Spring启动时自动设置 ApplicationEventPublisher** @param publisher*/@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher publisher) {this.publisher = publisher;System.out.println("UserServiceWithAware.publisher class: " + publisher.getClass().getName());// 输出:UserServiceWithAware.publisher class: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext}//其他业务代码...
}
启动应用后,上面两段代码中的publisher均能赋值完成,对应输出如下:
两种注入方式对比
方案 1(Aware
接口)的特点:
- 无需注解:完全依赖接口实现,适合旧版 Spring 或某些特殊场景(如无法修改构造函数的遗留代码)。
- 自动注入:Spring 容器在初始化 Bean 时自动调用
setXXX
方法。 - 灵活性:可以注入多个
Aware
接口(例如同时实现ApplicationContextAware
和BeanFactoryAware
)。 - 注意事项:Aware接口的set方法必须严格按照命名规范,比如setApplicationEventPublisher,这样Spring才能正确识别并调用。如果方法名不对,Spring可能无法正确注入。
方案 2(直接注入 ApplicationEventPublisher
)的优势:
- 更简洁:通过
@Autowired
或构造函数注入,代码更清晰。 - 符合现代 Spring 风格:推荐在新项目中使用,因为
Aware
接口在某些场景下可能显得冗余。
总结:Aware
接口适合需要与容器深度集成的场景,通过这种方式,Spring 实现了依赖注入的另一种形式,无需显式注解,完全依赖接口的约定。但现代开发更推荐直接通过依赖注入(如 @Autowired
)的方式。