1. 程式人生 > >spring原始碼-Aware-3.4 spring原始碼-bean之載入-2

spring原始碼-Aware-3.4 spring原始碼-bean之載入-2

  一、Aware介面,這個也是spring的拓展之一,為啥要單獨拿出來講呢,因為他相比於BeanFactoryPostProcessorBeanPostProcessor的實用性更加高,並且在具體的業務中也可以靈活使用,主要是能夠達到解耦的目的。

  二、常用的Aware介面有:第一類:BeanNameAware/BeanClassLoaderAware/BeanFactoryAware。 第二類:EmbeddedValueResolverAware/ResourceLoaderAware/ApplicationEventPublisherAware/MessageSourceAware/ApplicationContextAware。這兩類到底有啥區別類,其實沒有太大的區別。但是在原始碼實現中還是存在很大的差別的(後面統一說道)。

  三、原始碼實現:

  1、第一類:BeanNameAware/BeanClassLoaderAware/BeanFactoryAware

  1)實現方式:

import org.springframework.beans.factory.BeanNameAware;

/**
 * BeanNameAware/BeanClassLoaderAware/BeanFactoryAware類似
 */
public class TestBeanAware implements BeanNameAware{

    private String beanName;
    @Override
    
public void setBeanName(String beanName) { System.out.println(beanName); this.beanName = beanName; } public String getBeanName() { return beanName; } }

  2)有啥區別

  這裡簡單說明一下:相對於普通的bean,這裡可以獲取到beanName/classLoader/beanFactory。是對普通bean的一種增強,然後合理的應用才是關鍵

  3)原始碼實現部分:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                public Object run() {
                    AbstractAutowireCapableBeanFactory.this.invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, this.getAccessControlContext());
        } else {
            this.invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        }

        try {
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

    private void invokeAwareMethods(String beanName, Object bean) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware)bean).setBeanName(beanName);
        }

        if (bean instanceof BeanClassLoaderAware) {
            ((BeanClassLoaderAware)bean).setBeanClassLoader(this.getBeanClassLoader());
        }

        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware)bean).setBeanFactory(this);
        }

    }

  4)何時呼叫:spring原始碼-bean之載入-2 的3)點d.3 doCreateBean中的initializeBean()部分開始,所以這個其實是在getBean的時候才會呼叫。

  5)測試的時候發現:在增強容器中refresh方法中finishBeanFactoryInitializationh會完成這部分的呼叫

  

  2、第二類:EmbeddedValueResolverAware/ResourceLoaderAware/ApplicationEventPublisherAware/MessageSourceAware/ApplicationContextAware

  1)實現方式:這裡舉兩個例子EmbeddedValueResolverAware,ApplicationEventPublisherAware  

  a.EmbeddedValueResolverAware

import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.util.StringValueResolver;

import javax.annotation.PostConstruct;

public class TestEmbeddedValueResolverAware implements EmbeddedValueResolverAware {

    private StringValueResolver stringValueResolver;

    @Override
    public void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {
        this.stringValueResolver = stringValueResolver;
    }

    public String getProperties (String name) {
        String elName = "${"+ name +"}";
        return stringValueResolver.resolveStringValue(elName);
    }

    @PostConstruct
    public void test() {
        System.out.println(getProperties("name"));
    }
}

  注意:這裡是讀取方式配置

  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>aware.properties</value>
            </list>
        </property>
    </bean>

  aware.properties

name=test
age=25
sex=boy

  疑問:和這個有啥關係,看在StringValueResolver可以知道,這裡的StringValueResolver指向的是PropertyPlaceholderConfigurer的內部類PlaceholderResolvingStringValueResolver,當然具體的實現有不同的方式

  private class PlaceholderResolvingStringValueResolver implements StringValueResolver {
        private final PropertyPlaceholderHelper helper;
        private final PlaceholderResolver resolver;

        public PlaceholderResolvingStringValueResolver(Properties props) {
            this.helper = new PropertyPlaceholderHelper(PropertyPlaceholderConfigurer.this.placeholderPrefix, PropertyPlaceholderConfigurer.this.placeholderSuffix, PropertyPlaceholderConfigurer.this.valueSeparator, PropertyPlaceholderConfigurer.this.ignoreUnresolvablePlaceholders);
            this.resolver = PropertyPlaceholderConfigurer.this.new PropertyPlaceholderConfigurerResolver(props, (PropertyPlaceholderConfigurer.PropertyPlaceholderConfigurerResolver)null);
        }

        public String resolveStringValue(String strVal) throws BeansException {
            String value = this.helper.replacePlaceholders(strVal, this.resolver);
            return value.equals(PropertyPlaceholderConfigurer.this.nullValue) ? null : value;
        }
    }

  b.ApplicationEventPublisherAware

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;

import javax.annotation.PostConstruct;

public class TestApplicationEventPublisherAware implements ApplicationEventPublisherAware {

    private ApplicationEventPublisher publisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

    public ApplicationEventPublisher getPublisher() {
        return publisher;
    }

    public class TestEvent extends ApplicationEvent {

        private Object object;

        public TestEvent(Object source, Object object) {
            super(source);
            this.object = object;
        }

        public Object getObject() {
            return object;
        }
    }

    @PostConstruct
    public void test() {
        publisher.publishEvent(new TestEvent(this, "test"));
    }
import org.springframework.context.ApplicationListener;

public class TestListener implements ApplicationListener<TestApplicationEventPublisherAware.TestEvent>{

    @Override
    public void onApplicationEvent(TestApplicationEventPublisherAware.TestEvent testEvent) {
        System.out.println("TestEvent is Happen" + testEvent.getObject());
    }
}

  釋出,監聽的過程相信。在實際業務中很常用吧。這裡監聽過程後面會講,這裡不細說。

  注意:這裡用aware的介面方式實現釋出,監聽過程,會比直接呼叫的方式更加解耦。

  2)重點來了,這玩意在哪裡呼叫的呢。其實我們之前我們忽略了一個重點。

  a.先看呼叫方式

  

  看到postProcessBeforeInitialization應該感到高興了,因為這不就是實現了BeanPostProcessor介面的前置呼叫過程嗎。

  有問題可以參考:spring原始碼-BeanPostProcessor-3.3

  b.疑問:我們並沒有手動去實現BeanPostProcessor的介面並且對aware介面做處理啊。

  通過debug和檢視堆疊資訊可以知道方法呼叫在ApplicationContextAwareProcessor類裡面

package org.springframework.context.support;

import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.util.StringValueResolver;

class ApplicationContextAwareProcessor implements BeanPostProcessor {
    private final ConfigurableApplicationContext applicationContext;

    public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;
        if (System.getSecurityManager() != null && (bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                public Object run() {
                    ApplicationContextAwareProcessor.this.invokeAwareInterfaces(bean);
                    return null;
                }
            }, acc);
        } else {
            this.invokeAwareInterfaces(bean);
        }

        return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof EmbeddedValueResolverAware) {
            ((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(new ApplicationContextAwareProcessor.EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
        }

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

    }

    public Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }

    private static class EmbeddedValueResolver implements StringValueResolver {
        private final ConfigurableBeanFactory beanFactory;

        public EmbeddedValueResolver(ConfigurableBeanFactory beanFactory) {
            this.beanFactory = beanFactory;
        }

        public String resolveStringValue(String strVal) {
            return this.beanFactory.resolveEmbeddedValue(strVal);
        }
    }
}

  c、還有一個問題ApplicationContextAwareProcessor在哪裡註冊的呢?

   通過原始碼方式檢視到在refresh()this.prepareBeanFactory(beanFactory);中提前準備了ApplicationContextAwareProcessor

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.setBeanClassLoader(this.getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);
        if (beanFactory.containsBean("loadTimeWeaver")) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        Object systemEnvironment;
        if (!beanFactory.containsBean("systemProperties")) {
            try {
                systemEnvironment = System.getProperties();
            } catch (AccessControlException var4) {
                systemEnvironment = new ReadOnlySystemAttributesMap() {
                    protected String getSystemAttribute(String propertyName) {
                        try {
                            return System.getProperty(propertyName);
                        } catch (AccessControlException var3) {
                            if (AbstractApplicationContext.this.logger.isInfoEnabled()) {
                                AbstractApplicationContext.this.logger.info("Not allowed to obtain system property [" + propertyName + "]: " + var3.getMessage());
                            }

                            return null;
                        }
                    }
                };
            }

            beanFactory.registerSingleton("systemProperties", systemEnvironment);
        }

  四:Aware介面部分就這麼多吧,這裡沒有具體些實現和用法,但是相對於BeanFactoryPostProcessorBeanPostProcessor。Aware在實際應用中會更加常用,這一部分是spring提供出來的拓展,也是必要重要的一個部分。

  當然,我這裡可能還存在一些紕漏,還請大佬指出來!