【spring源碼分析】IOC容器初始化——查漏補缺(一)

前言:在【spring源碼分析】IOC容器初始化(十一)中提到了初始化bean的三個步驟:html

  • 激活Aware方法。
  • 後置處理器應用(before/after)。
  • 激活自定義的init方法。

這裏咱們就來看下Spring是如何激活Aware方法的。spring


Aware是什麼

Aware是一個空接口,包路徑爲:org.springframework.beans.factory.Aware,它具備標識做用,實現了該接口的bean具備被Spring容器通知的能力,通知的方式採用回調的方式。ide

因爲Aware是一個空接口,實際的方法簽名由各個子類來肯定,其該接口一般只會有一個接收單參數的set方法,該set方法的命名方式爲set+去掉接口中的Aware後綴,即:setxxx(),那Spring中是如何處理實現Aware接口的bean的呢。在invokeAwareMethods方法中能夠看到以下代碼:源碼分析

 1 // AbstractAutowireCapableBeanFactory
 2 private void invokeAwareMethods(final String beanName, final Object bean) {
 3         if (bean instanceof Aware) {
 4             // BeanNameAware
 5             if (bean instanceof BeanNameAware) {
 6                 ((BeanNameAware) bean).setBeanName(beanName);
 7             }
 8             // BeanClassLoaderAware
 9             if (bean instanceof BeanClassLoaderAware) {
10                 ClassLoader bcl = getBeanClassLoader();
11                 if (bcl != null) {
12                     ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
13                 }
14             }
15             // BeanFactoryAware
16             if (bean instanceof BeanFactoryAware) {
17                 ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
18             }
19         }
20     }

分析:測試

首先判斷bean是否實現了Aware接口,若是是則調用實例的setXXX()方法給實例設置xxx屬性,在invokeAwareMethods方法中,主要處理BeanNameAware、BeanClassLoaderAware、BeanFactoryAware三種接口,也從側面證明了Spring只會處理實現了這三種接口中任意一個的bean實例。this

Aware示例演示

下面就演示Spring是如何處理實現這三個接口的bean的:spa

 1 public class UserDefinedAware implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware {
 2 
 3     private String name;
 4     private ClassLoader classLoader;
 5     private BeanFactory beanFactory;
 6 
 7     @Override
 8     public void setBeanName(String name) {
 9         System.out.println("調用了 BeanNameAware 的 setBeanName方法");
10         this.name = name;
11     }
12 
13     @Override
14     public void setBeanClassLoader(ClassLoader classLoader) {
15         System.out.println("調用了 BeanClassLoader 的 setBeanClassLoader 方法");
16         this.classLoader = classLoader;
17     }
18 
19     @Override
20     public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
21         System.out.println("調用了 BeanFactoryAware 的 setBeanFactory 方法");
22         this.beanFactory = beanFactory;
23     }
24 
25     public void showMsg() {
26         System.out.println("beanName=" + this.name);
27         System.out.println("classLoader=" + this.classLoader.getClass());
28         System.out.println("是否爲單例=" + beanFactory.isSingleton(this.name));
29     }
30 }

測試方法以下:code

1     /**
2      * Aware接口演示
3      */
4     @Test
5     public void awareTest() {
6         ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:com/dev/config/aware/aware.xml");
7         UserDefinedAware userDefinedAware = context.getBean(UserDefinedAware.class);
8         userDefinedAware.showMsg();
9     }

輸出結果以下:xml

Aware總結

從以上示例基本上能夠了解 Aware接口 真正的含義:感知,實際上是Spring容器在初始化主動檢測當前bean是否實現了Aware接口,若是實現了則回調其set方法將相應的參數設置給該bean,這個時候該bean就從Spring容器中取得了相應的資源。因此Aware接口的做用就是讓實現該接口的bean能從Spring容器中取得相應的資源。這裏如name、ClassLoader、beanFactory。htm

下面列出一些經常使用的Aware接口,便於往後查詢:

  • LoadTimeWeaverAware:加載Spring Bean時織入第三方模塊,如AspectJ
  • BeanClassLoaderAware:加載Spring Bean的類加載器
  • BootstrapContextAware:資源適配器BootstrapContext,如JCA,CCI
  • ResourceLoaderAware:底層訪問資源的加載器
  • BeanFactoryAware:聲明BeanFactory
  • PortletConfigAware:PortletConfig
  • PortletContextAware:PortletContext
  • ServletConfigAware:ServletConfig
  • ServletContextAware:ServletContext
  • MessageSourceAware:國際化
  • ApplicationEventPublisherAware:應用事件
  • NotificationPublisherAware:JMX通知
  • BeanNameAware:獲取Spring Bean的名字

by Shawn Chen,2019.04.29,晚上。

相關文章
相關標籤/搜索