spring源碼閱讀筆記(一)

spring源碼閱讀筆記(一)


    最近工做不忙,抽空閱讀了下《spring源碼深度剖析》,特此作一下記錄。


    先說下BeanFactoryPostProcessor接口和BeanPostProcessor接口,這兩個接口都是spring 初始化bean時對外暴露的擴展點。兩個接口名稱看起來很類似,但做用及使用場景卻不一樣。


1.BeanFactoryPostProcessor
public interface BeanFactoryPostProcessor {
        void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
    }

    實現該接口,能夠在spring的bean建立以前,修改bean的定義屬性。也就是說,Spring容許BeanFactoryPostProcessor在容器實例化任何其它bean以前讀取配置元數據,並能夠根據須要進行修改,例如能夠把bean的scope從singleton改成prototype,也能夠把property的值給修改掉。能夠同時配置多個BeanFactoryPostProcessor,實現類能夠經過實現PriorityOrdered接口來控制各個BeanFactoryPostProcessor的執行次序。 java

    
    注意:BeanFactoryPostProcessor是在spring容器加載了bean的定義文件以後,在bean實例化以前執行的。接口方法的入參是ConfigurrableListableBeanFactory,使用該參數,能夠獲取到相關bean的定義信息。
    
    spring中內置了一些BeanFactoryPostProcessor實現類,經常使用的有: (org.springframework.beans.factory.config包下)
    1.PropertyPlaceholderConfigurer  替換xml中的佔位符爲*.properties文件中的值
    2.PropertyOverrideConfigurer  比PropertyPlaceholderConfigurer功能高級些,支持缺省值
    3.CustomEditorConfigurer:用來註冊自定義的屬性編輯器

    例如自定義一個BeanFactoryPostProcessor:

public MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 
                throw BeansException {
            BeanDefinition bd = beanFactory.getBeanDefinition("myJavaBean");
            MutablePropertyValues mpv = bd.getPropertyValues();
            mpv.addPropertyValue("propertyName", "newValue");
        }
    }
    xml中配置一下:
<bean class="com.test.MyBeanFactoryPostProcessor" />
2.BeanPostProcessor

public interface BeanPostProcessor {
        Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
        Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
    }

    BeanPostProcessor能夠在spring容器實例化bean以後,在執行bean的初始化方法先後,添加一些本身的處
理邏輯。這裏的初始化方法包括bean實現InitializingBean接口的afterPropertiesSet方法和在配置文件中指定
的init-method方法。

    其具體的執行過程爲:
   

    spring中有一些內置的BeanPostProcessor實現類,例如

    1.org.springframework.context.annotation.CommonAnnotationBeanPostProcessor: 支持@Resource註解的注入
    2.org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor: 支持@Required註解的注入
    3.org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor: 支持@Autowired註解的注入
    4.org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor:支持@PersistenceUnit和@PersistenceContext註解的注入
    5.org.springframework.context.support.ApplicationContextAwareProcessor: 用來爲bean注入ApplicationContext等容器對象
    
    這些註解類會在配置文件中經過配置<context:component-scan base-package="*.*" />後自動進行註冊。

    還有aop中的功能也是經過實現BeanPostProcessor接口去作的代理,有興趣的同窗能夠去看下
AspectJAwareAdvisorAutoProxyCreator類,其父類AbstractAutoProxyCreator中實現了postProcessAfterInitialization
接口完成了對方法的代理。代碼以下:

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.containsKey(cacheKey)) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) {
            return bean;
        }
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // Create proxy if we have advice.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    protected Object createProxy(
            Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

        ProxyFactory proxyFactory = new ProxyFactory();
        // Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
        proxyFactory.copyFrom(this);

        if (!shouldProxyTargetClass(beanClass, beanName)) {
            // Must allow for introductions; can't just set interfaces to
            // the target's interfaces only.
            Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
            for (Class<?> targetInterface : targetInterfaces) {
                proxyFactory.addInterface(targetInterface);
            }
        }

        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        for (Advisor advisor : advisors) {
            proxyFactory.addAdvisor(advisor);
        }

        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);

        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }

        return proxyFactory.getProxy(this.proxyClassLoader);
    }

    [proxyFactory]
    public Object getProxy(ClassLoader classLoader) {
        return createAopProxy().getProxy(classLoader);
    }

    [JdkDynamicAopProxy]
    public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
        }
        Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }
    若是你有一些其餘獨特的需求也能夠仿照上面的方式本身寫一個BeanPostProcessor註冊到容器中。

3.InitializingBean和init-method

    這兩個方法的調用點是AbstractAutowireCapableBeanFactory類的invokeInitMethods方法:

   咱們看下代碼: spring

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
            throws Throwable {

        boolean isInitializingBean = (bean instanceof InitializingBean);
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
            if (logger.isDebugEnabled()) {
                logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
            }
            if (System.getSecurityManager() != null) {
                try {
                    AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        public Object run() throws Exception {
                            ((InitializingBean) bean).afterPropertiesSet();
                            return null;
                        }
                    }, getAccessControlContext());
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                ((InitializingBean) bean).afterPropertiesSet();
            }
        }

        if (mbd != null) {
            String initMethodName = mbd.getInitMethodName();
            if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                    !mbd.isExternallyManagedInitMethod(initMethodName)) {
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }
    可是invokeInitMethods方法又是在哪裏調用的呢?是同一個類中的initializeBean方法調用的,代碼以下:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, 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;
    }
    咱們能夠看到這裏首先調用了bean的Aware接口的一些相關方法,而後是調用BeanPostProcessor接口的前置處理, 而後調用上面的bean初始化方法,而後是BeanPostProcessor的後置處理,這正好符合了上圖中描述的調用順序。     其中Aware有不少子接口,像BeanNameAware,BeanClassLoaderAware,BeanFactoryAware等等,用戶能夠編寫實現 了這些接口的bean,這樣在spring回調aware相關接口的時候獲取到一些容器的相關信息。     下面簡單說下使用InitializingBean和init-method方法初始化bean的區別:     1.實現InitializingBean接口是直接調用afterPropertiesSet方法,比經過反射調用init-method指定的方法效率相對來講要高點。 可是init-method方式消除了對spring的依賴     2:若是調用afterPropertiesSet方法時出錯,則不調用init-method指定的方法。
相關文章
相關標籤/搜索