首頁 > 軟體

Spring Aware原始碼設計範例解析

2023-01-16 14:00:38

1. Aware介紹

前一篇講到了BeanPostProcessor的相關知識,我們知道BeanPostProcessor是對整個容器中的Bean做前置和後置增強處理。這樣的實現方式限制了開發者只能按照Spring提供的模板,對Bean做前置和後置的增強,這樣雖然已經很靈活了,但是如果開發者想要對Spring中的Bean做更復雜的操作或者開發者想要使用Spring中的BeanFactory、ClassLoader時,這樣的方式明顯就不夠方便了,因此Spring也考慮到了這樣的情況,就提供了另外的方式提升Spring的擴充套件性和靈活性,這種方式就是Aware。

單純說Aware可能不熟悉,但是如果說BeanNameAware、BeanFactoryAware那麼是不是就知道這個Aware到底是何方神聖了。

接下來就說一下Spring提供給開發者Aware的這個功能。

Spring中Aware的原始碼如下:

public interface Aware {
}

從原始碼中可以看到Aware就是一個簡單的介面,該介面是一個無實現的介面,一般看到這種介面可以都是作為最頂級的父類別介面使用的,使用時一般都是instanceof判斷是否是頂級介面型別。

2. Aware類別

在Spring中Aware有幾個繼承介面,分別是:

  • BeanClassLoaderAware
  • BeanFactoryAware
  • BeanNameAware

2.1 BeanClassLoaderAware

首先是BeanClassLoaderAware介面,從字面意思翻譯就可以大概知道這是一個關於Bean的類載入器的介面,因此該介面的功能就聚焦在類載入器上。

BeanClassLoaderAware原始碼如下:

public interface BeanClassLoaderAware extends Aware {
	//set方法,賦值ClassLoader方法
	void setBeanClassLoader(ClassLoader classLoader);
}

從原始碼可以看到該介面只提供了一個setBeanClassLoader方法,該方法就是簡單的設定Bean的類載入器的方法,所以從這個方法中就可以知道BeanClassLoaderAware就單純提供了一個賦值ClassLoader的方法,這裡的介面並不會指定ClassLoader的接收方,因此接收方需要在實現該介面的實現類中指定,然後將ClassLoader賦值給實現類中的具體常數。

2.2 BeanFactoryAware

BeanFactoryAware介面,看到這個就立馬想到Spring中的BeanFactory,BeanFactory在Spring中是作為Bean的工廠,那麼該介面一定是與BeanFactory相關的介面。

BeanFactoryAware原始碼如下:

public interface BeanFactoryAware extends Aware {
    void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}

從原始碼中可以看到BeanFactoryAware跟BeanClassLoaderAware相似都只提供了一個set方法,該介面中只定義了setBeanFactory一個方法。

該介面中的方法 功能跟BeanClassLoaderAware功能相同,都是賦值,但是該介面賦值的是BeanFactory。

2.3 BeanNameAware

原始碼如下:

public interface BeanNameAware extends Aware {
    void setBeanName(String name);
}

該介面功能同上。(說實話實際開發中沒用到過這個,只用過前兩個,所以我也沒搞懂該類到底可以幹啥)。

2.4 ApplicationContextAware

該介面則是一個特別的介面了,因為該介面跟前三個繼承Aware的介面不同,ApplicationContextAware並不是spring-bean中提供的介面,而是在spring-context中提供的介面,該介面是從spring-context包中提供的介面,該介面的作用也是跟前三個類似,並且大部分開發者用的最多的也是這個。

原始碼如下:

public interface ApplicationContextAware extends Aware {
    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    @Nullable
    String getId();
    String getApplicationName();
    String getDisplayName();
    long getStartupDate();
    @Nullable
    ApplicationContext getParent();
    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}

原始碼中也是簡單的賦值操作,但是賦值的物件是ApplicationContext物件,對於這個物件使用Spring的一定不陌生。

可以這樣說:ApplicationContext給了開發者最多的許可權用於操作Bean。

從ApplicationContext原始碼中也可以看到該介面繼承了ListableBeanFactory、HierarchicalBeanFactory、ApplicationEventPublisher等其它介面,這樣就將更多的Bean的許可權通過ApplicationContext下放給開發者!(又是被Spring的高靈活性折服的時刻)。

3. Aware的使用

@Component
public class MySpringAware implements BeanFactoryAware, BeanClassLoaderAware, ApplicationContextAware, BeanNameAware {
    private ApplicationContext applicationContext;
    private ListableBeanFactory beanFactory;
    private ClassLoader classLoader;
    private String beanName;
    /**
     * 獲取某個介面下的所有實現類
     *
     * @param filter
     */
    public void registryFilter(FilterProcessor filter) {
        Map<String, MyFilter> beans = beanFactory.getBeansOfType(MyFilter.class);
        beans.values().stream().sorted(AnnotationAwareOrderComparator.INSTANCE).forEach(filter::register);
    }
        /**
     * 獲取環境設定
     *
     * @return
     */
    public Environment getApplicationData() {
        return applicationContext.getEnvironment();
    }
    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = (ListableBeanFactory) beanFactory;
    }
    @Override
    public void setBeanName(String s) {
        this.beanName = s;
    }
}
@Component
public class FilterProcessor {
    private final List<MyFilter> filterList = new ArrayList();
    public void register(MyFilter filter) {
        this.filterList.add(filter);
    }
    public List<MyFilter> getFilterList() {
        return filterList;
    }
}
public interface MyFilter {
    void doFilter();
}
@Component
@Order(1)
public class MyDemoFilter extends FilterProcessor implements MyFilter{
    @Override
    public void doFilter() {
        System.out.println("執行第一個過濾器MyDemoFilter");
    }
}
@Component
@Order(2)
public class MyDemoFilter2 extends FilterProcessor implements MyFilter{
    @Override
    public void doFilter() {
        System.out.println("執行第二個過濾器MyDemoFilter2");
    }
}

執行結果:

以上的例子中通過MySpringAware實現了前文中說到的幾個Aware,分別使用了其中的BeanFactory和ApplicationContext。這樣在MySpringAware中就可以使用我們定義的常數接收Spring容器中的BeanFactory、ClassLoader、ApplicationContext等功能。

4. Aware的作用

從以上的例子中可以看到,Aware為開發者提供了插樁式的介面,開發者只要實現該介面就可以獲得Spring容器的某些管理權。

比如BeanClassLoaderAware是獲得對Bean的類載入器的管理權。

BeanFactoryAware是活的對Bean工廠的管理權。

這樣插樁式的擴充套件可以保證開發者在使用時可以獲得Spring中某些功能的管理權,方便開發者對Spring的理解和使用,不需要複雜的實現就可以獲得Spring內部的管理。

5. Aware的呼叫

前面說完了Aware的介紹、類別和作用,最後來說實現Aware相關介面的實現類在Spring中是如何被呼叫的。

實現Aware相關介面的實現類被呼叫的方式與前面講的BeanPostProcessor有一定區別。

區別如下:

BeanPostProcessor的呼叫:

  • 呼叫方式:註冊+讀取註冊列表(通過register.List和遍歷beanPostProcessorList)
  • 呼叫時機:Bean執行初始化函數(invokeInitMethods)之前或者之後

Aware的呼叫:

  • 呼叫方式:通過Bean是否實現了Aware/BeanClassLoaderAware/BeanFactoryAware,然後呼叫相應的實現類的重寫方法
  • 呼叫時機:Bean執行初始化函數(invokeInitMethods)之前且beanPostProcessor#before之前

原始碼如下:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
		implements AutowireCapableBeanFactory {
    //初始化Bean的方法
	protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                //呼叫Bean的Aware重寫介面
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
            //呼叫Bean的Aware重寫介面
			invokeAwareMethods(beanName, bean);
		}
		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
            //呼叫BeanPostProcessor前置介面
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}
		try {
            //呼叫Bean的初始化函數
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
            //呼叫BeanPostProcessor後置介面
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}
	//呼叫Aware的實現
    private void invokeAwareMethods(String beanName, Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
            if (bean instanceof BeanClassLoaderAware) {
                ClassLoader bcl = getBeanClassLoader();
                if (bcl != null) {
                    ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
                }
            }
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
            }
        }
    }
}

區別梳理如下:

以AbstractAutowireCapableBeanFactory為主線梳理呼叫Aware介面的鏈路如下:

  • org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods

對於ApplicationContextAware的呼叫鏈路梳理如下:

  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
  • org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization
  • org.springframework.context.support.ApplicationContextAwareProcessor#invokeAwareInterfaces

根據以上的鏈路可以很清晰的看到ApplicationContextAware的呼叫實現。

以上就是Spring Aware原始碼設計範例解析的詳細內容,更多關於Spring Aware原始碼設計的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com