1. 程式人生 > 實用技巧 >Spring原始碼解析(八)--@PostConstruct

Spring原始碼解析(八)--@PostConstruct

最近想寫點,細小的知識點,從這些細小的知識點入手看看我們常用的一些spring方法是怎麼實現的

  一 初始化Bean的流程

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
    if (instanceWrapper == null) {
                // 建立 Bean 例項
        instanceWrapper = createBeanInstance(beanName, mbd, args);//1
} ...
synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { // 呼叫 MergedBeanDefinitionPostProcessor 回撥(在這裡完成相關方法的掃描及儲存) applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } mbd.postProcessed
= true; } } // 初始化 Bean 例項 Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper);//2 // 在這裡進行 @PostConstruct 方法的呼叫 exposedObject = initializeBean(beanName, exposedObject, mbd);//3 } ... return exposedObject; }

  對一個bean進行初始化分為3步

  1 例項化,說白了new出來先createBeanInstance

  2 填充欄位,比如@Autowired註解就在這裡完成的,下一篇就分析@Autowired,populateBean

  3 執行使用者指定的,或者配置的@PostConstructinitializeBean

二 準備元資料

    protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof MergedBeanDefinitionPostProcessor) {
                MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
                bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
            }
        }
    }

  那麼對於MergedBeanDefinitionPostProcessor 它的實現類有哪些呢

  

  比如我們現在正在分析的@PostConstruct 對它進行處理的就是InitDestroyAnnotationBeanPostProcessor ,及其子類CommonAnnotationBeanPostProcessor

  

@Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        if (beanType != null) {
            LifecycleMetadata metadata = findLifecycleMetadata(beanType);
            metadata.checkConfigMembers(beanDefinition);
        }
    }
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
        if (this.lifecycleMetadataCache == null) {
            // Happens after deserialization, during destruction...
            return buildLifecycleMetadata(clazz);
        }
        // Quick check on the concurrent map first, with minimal locking.
        LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);//快取這些東西不管,直接分析buildLifecycleMetadata
        if (metadata == null) {
            synchronized (this.lifecycleMetadataCache) {
                metadata = this.lifecycleMetadataCache.get(clazz);
                if (metadata == null) {
                    metadata = buildLifecycleMetadata(clazz);
                    this.lifecycleMetadataCache.put(clazz, metadata);
                }
                return metadata;
            }
        }
        return metadata;
    }
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
        final boolean debug = logger.isDebugEnabled();
        LinkedList<LifecycleElement> initMethods = new LinkedList<LifecycleElement>();
        LinkedList<LifecycleElement> destroyMethods = new LinkedList<LifecycleElement>();
        Class<?> targetClass = clazz;

        do {
            final LinkedList<LifecycleElement> currInitMethods = new LinkedList<LifecycleElement>();
            final LinkedList<LifecycleElement> currDestroyMethods = new LinkedList<LifecycleElement>();

            ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() {
                @Override
                public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
                    if (initAnnotationType != null) {
                        if (method.getAnnotation(initAnnotationType) != null) {
                            LifecycleElement element = new LifecycleElement(method);
                            currInitMethods.add(element);
                            if (debug) {
                                logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
                            }
                        }
                    }
initAnnotationType的值是什麼呢?
在它的子類進行了賦值
public CommonAnnotationBeanPostProcessor() {
        setOrder(Ordered.LOWEST_PRECEDENCE - 3);
        setInitAnnotationType(PostConstruct.class);
        setDestroyAnnotationType(PreDestroy.class);
        ignoreResourceType("javax.xml.ws.WebServiceContext");
    }

  重點看看,就是使用java反射得到全部的method,然後呼叫介面MethodCallback的實現邏輯

public static void doWithLocalMethods(Class<?> clazz, MethodCallback mc) {
        Method[] methods = getDeclaredMethods(clazz);
        for (Method method : methods) {
            try {
                mc.doWith(method);
            }
            catch (IllegalAccessException ex) {
                throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
            }
        }
    }

  判斷某一個方法是否有註解PostConstruct,有就先構造成LifecycleElement,並放入currInitMethods,快取起來

      if (initAnnotationType != null) {
                        if (method.getAnnotation(initAnnotationType) != null) {
                            LifecycleElement element = new LifecycleElement(method);
                            currInitMethods.add(element);

  最後把這些資訊封裝一下

  return new LifecycleMetadata(clazz, initMethods, destroyMethods);

  還要進行一次快取

private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
        if (this.lifecycleMetadataCache == null) {
            // Happens after deserialization, during destruction...
            return buildLifecycleMetadata(clazz);
        }
        // Quick check on the concurrent map first, with minimal locking.
        LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
        if (metadata == null) {
            synchronized (this.lifecycleMetadataCache) {
                metadata = this.lifecycleMetadataCache.get(clazz);
                if (metadata == null) {
                    metadata = buildLifecycleMetadata(clazz);
                    this.lifecycleMetadataCache.put(clazz, metadata);//快取起來
                }
                return metadata;
            }
        }
        return metadata;
    }

  資料準備部分就分析好了