Spring原始碼解析(八)--@PostConstruct
阿新 • • 發佈:2020-11-13
最近想寫點,細小的知識點,從這些細小的知識點入手看看我們常用的一些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; }
資料準備部分就分析好了