Aware 接口用于注入一些與容器相關信息,例如:
? a. BeanNameAware 注入 Bean 的名字
? b. BeanFactoryAware 注入 BeanFactory 容器
? c. ApplicationContextAware 注入 ApplicationContext 容器
? d. EmbeddedValueResolverAware 注入 解析器,解析${}
為什么有了@autowired還需要用Aware,因為autowired會存在失效的問題
在 Spring 框架里,@Autowired和Aware接口有著不同的設計目的,它們并非簡單的替代關系。下面詳細分析它們的差異以及@Autowired可能失效的場景。
1. @Autowired 的工作原理與局限
@Autowired借助依賴注入(DI)的方式,把 Spring 容器中的 bean 自動注入到目標組件里。不過,它存在以下幾方面的限制:生命周期的制約:@Autowired主要在 bean 的實例化和屬性填充階段發揮作用。要是你需要在 bean 初始化的更早階段獲取某些資源,@Autowired就無法滿足需求了。
靜態環境的不適用:由于靜態變量或方法不屬于某個具體的 bean 實例,所以@Autowired不能直接對靜態字段進行注入。
ApplicationContext 依賴問題:如果要獲取ApplicationContext本身,使用@Autowired會形成循環依賴,比如在自定義 bean 處理器中就可能遇到這種情況。2. Aware 接口的作用
Aware接口是 Spring 提供的一種回調機制,它允許 bean 在初始化過程中獲取容器的特定資源。常見的Aware接口有:ApplicationContextAware:能獲取ApplicationContext。
BeanNameAware:可以獲取當前 bean 的名稱。
EnvironmentAware:能夠獲取環境配置信息。
簡單的來說
@Autowired的解析依賴于 bean 后處理器,屬于擴展功能。也就是說@Autowired注解的功能實現是借助 Spring 的
bean 后處理器來完成的,在 bean 的生命周期中,@Autowired的解析處理是在特定的擴展流程里進行的。
Aware 接口屬于內置功能,無需添加任何擴展 Spring 就能識別。這意味著在 Spring 容器的核心流程中,Aware
接口相關方法會被調用,在某些場景下,因為@Autowired屬于擴展功能,可能會在一些特殊情況下失效,而作為內置功能的 Aware
接口不會出現這種問題。例如在某些場景下,使用 Aware 接口注入 ApplicationContext
能成功,但是使用@Autowired注入 ApplicationContext 卻會失敗 。
public class MyBean implements BeanNameAware, ApplicationContextAware, InitializingBean {@Overridepublic void setBeanName(String name) {log.debug("當前bean:" + this + ",實現 BeanNameAware 調用的方法,名字叫:" + name);}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {log.debug("當前bean:" + this + ",實現 ApplicationContextAware 調用的方法,容器叫:" + applicationContext);}@Overridepublic void afterPropertiesSet() throws Exception {log.debug("當前bean:" + this + ",實現 InitializingBean 調用的方法,初始化");}@Autowiredpublic void aaa(ApplicationContext applicationContext) {log.debug("當前bean:" + this +",使用 @Autowired 容器是:" + applicationContext);}@PostConstructpublic void init() {log.debug("當前bean:" + this + ",使用 @PostConstruct 初始化");}
}
public class TestAwareAndInitializingBean {@Testpublic void testAware1() throws Exception {GenericApplicationContext context = new GenericApplicationContext();context.registerBean("myBean", MyBean.class);context.refresh();context.close();}
}