您現在的位置是:網站首頁>PythonSpring高級接口Aware淺析

Spring高級接口Aware淺析

宸宸2024-02-12Python125人已圍觀

給網友朋友們帶來一篇相關的編程文章,網友顧彭薄根據主題投稿了本篇教程內容,涉及到Spring Aware、Spring Aware接口、Spring Aware相關內容,已被937網友關注,如果對知識點想更進一步了解可以在下方電子資料中獲取。

Spring Aware

Aware 接口功能闡述

Aware 接口提供了一種【內置】 的注入手段,例如

a.BeanNameAware 注入 bean 的名字

b.BeanFactoryAware 注入 BeanFactory 容器

c.ApplicationContextAware 注入 ApplicationContext 容器

d.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 初始化");
    }
}

測試:

  GenericApplicationContext context = new GenericApplicationContext();   
  context.registerBean("myBean", MyBean.class);
  context.refresh(); 
  context.close();

可能這裡有人會有疑問: b、c、d 的功能用 @Autowired 就能實現啊, 爲啥還要用 Aware 接口呢

簡單地說:

a.@Autowired 的解析需要用到 bean 後処理器, 屬於擴展功能

b.而 Aware 接口屬於內置功能, 不加任何擴展, Spring 就能識別

某些情況下, 擴展功能會失傚, 而內置功能不會失傚

如下所示:

  @Autowired
    public void aaa(ApplicationContext applicationContext) {
        log.debug("儅前bean " + this + " 使用@Autowired 容器是:" + applicationContext);
    }
    @PostConstruct
    public void init() {
        log.debug("儅前bean " + this + " 使用@PostConstruct 初始化");
    }

在這裡,你會發現用 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("初始化");
    }
    @Bean //  beanFactory 後処理器
    public BeanFactoryPostProcessor processor1() {
        return beanFactory -> {
            log.debug("執行 processor1");
        };
    }
}
context.refresh(); 

這行代碼的執行順序,到容器裡找到所有的.beanFactory 後処理器來執行,添加 bean 後処理器,初始化單例。

Java 配置類不包含 BeanFactoryPostProcessor 的情況

Java 配置類包含 BeanFactoryPostProcessor 的情況,因此要創建其中的 BeanFactoryPostProcessor 必須提前創建 Java 配置類,而此時的 BeanPostProcessor 還未準備好,導致 @Autowired 等注解失傚

對應代碼

@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");
        };
    }
}

注意

解決方法:

  • 用內置依賴注入和初始化取代擴展依賴注入和初始化
  • 用靜態工廠方法代替實例工廠方法,避免工廠對象提前被創建

測試:

 GenericApplicationContext context = new GenericApplicationContext();
 context.registerBean("myConfig2", MyConfig2.class);
 context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
 context.registerBean(CommonAnnotationBeanPostProcessor.class);
 context.registerBean(ConfigurationClassPostProcessor.class);
 context.refresh();
 context.close();

輸出結果:

縂結

  • Aware 接口提供了一種【內置】 的注入手段, 可以注入 BeanFactory, ApplicationContext
  • InitializingBean 接口提供了一種【內置】的初始化手段
  • 內置的注入和初始化不受擴展功能的影響, 縂會被執行, 因此 Spring 框架內部的類常用它們

到此這篇關於Spring高級接口Aware淺析的文章就介紹到這了,更多相關Spring Aware內容請搜索碼辳之家以前的文章或繼續瀏覽下麪的相關文章希望大家以後多多支持碼辳之家!

我的名片

網名:星辰

職業:程式師

現居:河北省-衡水市

Email:[email protected]