spring源碼:Aware接口

1、spring容器中的aware接口介紹java

  Spring中提供了各類Aware接口,比較常見的如BeanFactoryAware,BeanNameAware,ApplicationContextAware,BeanClassLoaderAware等,方便從上下文中獲取當前的運行環境。咱們先從使用的角度來講明aware接口的使用方式,舉例如咱們想獲得當前的BeanFactory,咱們可讓咱們的實現類繼承BeanFactoryAware接口,而後經過接口注入的方式獲得當前容器中的BeanFactory:web

public class Fruit implements BeanFactoryAware {
    private BeanFactory beanFactory;
 
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
}

咱們的Fruit類實現了aware接口,若是咱們直接在應用中new一個Fruit的對象,固然是拿不到beanFactory變量的,咱們必須在spring的配置文件中聲明咱們的fruit對象才行,也就是說fruit對象必須交給容器進行管理,容器幫你把各類aware接口中想要注入的對象設置到bean中。具體看容器管理aware接口的代碼實現,代碼在AbstractAutowireCapableBeanFactory的initializeBean方法中:spring

protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
    // 判斷對象實現的接口類型,處理特定的三種接口類型:BeanNameAware、BeanClassLoaderAware和BeanFactoryAware。
    if (bean instanceof BeanNameAware) {
        ((BeanNameAware) bean).setBeanName(beanName);
    }
 
    if (bean instanceof BeanClassLoaderAware) {
        ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
    }
 
    if (bean instanceof BeanFactoryAware) {
        ((BeanFactoryAware) bean).setBeanFactory(this);
    }
    // 開始Bean初始化前處理、初始化、初始化後處理
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
 
    try {
        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()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

能夠看出來,aware接口的各類處理是在屬性設置完成以後、bean初始化以前完成的。顯然的,若是咱們直接new出來一個bean,這些框架性的特性是沒有使用到的。除了BeanFactoryAware、BeanNameAware、BeanClassLoaderAware以外的那些aware接口,好比ApplicationContextAware,再好比Webx中的自定義aware接口,它們又是怎麼作到接口注入的呢?原來在應用中建立上下文容器時會註冊一個BeanPostProcessor------ApplicationContextAwareProcessor,在這個類裏面進行了context的注入,這樣咱們就能可以拿到bean中的context對象:app

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof ResourceLoaderAware) {
        ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
    }
    if (bean instanceof ApplicationEventPublisherAware) {
        ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
    }
    if (bean instanceof MessageSourceAware) {
        ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
    }
    if (bean instanceof ApplicationContextAware) {
        ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
    }
    return bean;
}

那麼容器是在何時把ApplicationContextAwareProcessor的對象註冊到context的BeanPostProcessor列表中的呢,奧祕在org.springframework.context.support.AbstractApplicationContext.prepareBeanFactory(ConfigurableListableBeanFactory)方法中:框架

// Tell the internal bean factory to use the context's class loader.
beanFactory.setBeanClassLoader(getClassLoader());
 
// Populate the bean factory with context-specific resource editors.
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
 
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); //在這裏註冊了咱們想要的BeanPostProcessor
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

2、瞭解webx中實現的aware接口ide

  咱們瞭解了aware的實現原理,咱們就能夠本身來實現本身的aware接口了。Webx就是這麼作的(webx自己做爲一個容器,自己註冊了各種aware接口的BeanPostProcessor),好比咱們想要感知到當前環境是不是生產模式,咱們只須要實現ProductionModeAware接口就可以得到生產模式的值了。咱們使用aware接口感受很神奇很簡便,緣由是不少工做框架已經幫咱們作了。webx中使用ProductionModeAwarePostProcessor這個BeanPostProcessor來進行生產模式的注入。在postProcessBeforeInitialization方法中:post

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof ProductionModeAware) {
        ((ProductionModeAware) bean).setProductionMode(configuration.isProductionMode());
    }
 
    return bean;
}

因此任何實現了ProductionModeAware接口的類,在webx容器中都可以得到生產模式的取值。測試

3、自定義aware接口實現ui

  瞭解了箇中原理,那麼自定義aware接口實現起來並不複雜。咱們只須要2步操做:1.實現咱們aware接口的postprocessor,並在容器中註冊;2.bean實體類集成咱們自定義的aware接口並實現。代碼以下:Aware接口比較簡單,就作一件事情,把Apple對象注入。this

public interface AppleAware {
    void setApple(Apple a);
}

咱們的BeanPostProcessor會檢查是不是AppleAware接口,由於註冊到容器的BeanPostProcessor會對每個bean都作一次掃描:

public class AppleAwarePostProcessor implements BeanPostProcessor {
 
    private Apple a;
 
    public AppleAwarePostProcessor(Apple a) {
        this.a = a;
    }
 
    /* (non-Javadoc)
     * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof AppleAware) {
            ((AppleAware) bean).setApple(a);
        }
        return bean;
    }
 
    /* (non-Javadoc)
     * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // TODO Auto-generated method stub
        return bean;
    }
 
}

實體類Market實現了AppleAware接口,可以獲得Apple對象的注入:

public class Market implements AppleAware {
 
    private Apple a;
 
    @Override
    public void setApple(Apple a) {
         this.a = a;
    }
 
    public String getName() {
        return a.getName();
    }
 
}

最後是咱們的測試類,必定要把咱們的BeanPostProcessor加入到當前容器中,這一點很是重要:

public class TestAware {
    public static void main(String args[]) {
        ConfigurableBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
        BeanPostProcessor bpp = new AppleAwarePostProcessor((Apple)beanFactory.getBean("apple"));
    // 工廠對象中加入咱們自定義的BeanPostProcessor
        beanFactory.addBeanPostProcessor(bpp);
        Market market = (Market) beanFactory.getBean("market");
        System.out.println(market.getName());
    }
}

4、

相關文章
相關標籤/搜索