【Spring】Bean的LifeCycle(生命周期)
菜瓜:水稻,上次說Bean的LifeCycle,還沒講完
水稻:啥?說人話?
菜瓜:spring,bean,生命周期
水稻:。。。那你真的是很棒棒哦!。。。bean生命周期的話,從BeanFactory、ApplicationContext和FactoryBean開始說起
- 我們知道(你不一定知道)BeanFactory是Spring訪問Bean容器的根接口,源碼的註釋: “The root interface for accessing a Spring bean container.”
- 而ApplicationContext繼承自BeanFactory,也就是說它具有BeanFactory的屬性和方法,並進一步完善(繼承其他的接口)
- FactoryBean跟前兩個關係就不怎麼大了,它是spring提供給用戶創建bean的口子,有一些bean創建過程複雜,或者依賴第三方包等(Mybatis-Spring中),可交給用戶自己創建
菜瓜:嗯。。陷入沉思。。(欲言又止)
水稻:講理論不給代碼就是耍流氓
-
package com.vip.qc.postprocessor; import org.springframework.beans.factory.FactoryBean; import org.springframework.stereotype.Component; /** * @author QuCheng on 2020/6/15. */ @Component("fb") public class FactoryBeanT implements FactoryBean<FactoryBeanT.CustomBean> { public FactoryBeanT() { System.out.println("實現FactoryBean接口的類自身被放在IOC一級緩存的容器裏面,getObject的對象是在另一個緩存對象中"); } @Override public CustomBean getObject() { return new CustomBean(); } @Override public Class<?> getObjectType() { return CustomBean.class; } static class CustomBean { public CustomBean() { System.out.println("自定義bean"); } } } 測試方法 @Test public void testTransa() { BeanFactory context = new AnnotationConfigApplicationContext(ComponentScanD.class); System.out.println("factoryBean : " + context.getBean("fb")); System.out.println("&factoryBean : " + context.getBean("&fb")); }
測試結果實現FactoryBean接口的類自身被放在IOC一級緩存的容器裏面,getObject的對象是在另一個緩存對象中
自定義bean
factoryBean : com.vip.qc.postprocessor.FactoryBeanT$CustomBean@214b199c
&factoryBean : com.vip.qc.postprocessor.FactoryBeanT@20d3d15a
菜瓜:懂了,BeanFactory是Spring的核心–容器,ApplicationContext則是包裹容器的上下文,豐富容器的功能(資源加載,事件驅動等)。FactoryBean也是Spring擴展性的提現
水稻:WC,你這個總結提到了精髓。就是擴展性:如果BeanFactory是核心思想,那麼其他的上下文,後置處理器,還是Aware接口等等,都是為了實現擴展
菜瓜:鋪墊說完了,開始生命周期唄
水稻:這次咱們反過來先看源碼,再看實驗,再總結
- BeanFactory源碼註釋 – 定義了實現的生命周期
-
* @author Rod Johnson * @author Juergen Hoeller * @author Chris Beams * @since 13 April 2001 * @see BeanNameAware#setBeanName * @see BeanClassLoaderAware#setBeanClassLoader * @see BeanFactoryAware#setBeanFactory * @see org.springframework.context.ResourceLoaderAware#setResourceLoader * @see org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher * @see org.springframework.context.MessageSourceAware#setMessageSource * @see org.springframework.context.ApplicationContextAware#setApplicationContext * @see org.springframework.web.context.ServletContextAware#setServletContext * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization * @see InitializingBean#afterPropertiesSet * @see org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization * @see DisposableBean#destroy * @see org.springframework.beans.factory.support.RootBeanDefinition#getDestroyMethodName */ public interface BeanFactory {
- BeanFactory源碼實現類
-
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { // BeanNameAware BeanFactoryAware ... invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // BeanPostProcessor Before @PostConstruct wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // initMethod InitializingBean接口 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()) { // BeanPostProcessor after wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
- 實驗代碼
-
package com.vip.qc.postprocessor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.stereotype.Component; /** * @author QuCheng on 2020/6/14. */ @Component public class BeanFactoryPostProcessorT implements BeanFactoryPostProcessor { public static final String BEAN_NAME = "initializingBeanT"; @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { BeanDefinition initializingBeanT = beanFactory.getBeanDefinition(BEAN_NAME); System.out.println("BeanFactoryPostProcessor bean " + initializingBeanT.getBeanClassName()); } } package com.vip.qc.postprocessor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; /** * @author QuCheng on 2020/6/14. */ @Component public class BeanPostProcessorT implements BeanPostProcessor { public static final String BEAN_NAMET = "initializingBeanT"; @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (BEAN_NAMET.equals(beanName)) { InitializingBeanT processorT = ((InitializingBeanT) bean); System.out.println("BeanPostProcessor BeforeInitialization " + processorT); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (BEAN_NAMET.equals(beanName)){ InitializingBeanT processorT = ((InitializingBeanT) bean); System.out.println("BeanPostProcessor AfterInitialization " + processorT); } return bean; } } package com.vip.qc.postprocessor; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; /** * @author QuCheng on 2020/6/14. */ @Component public class InitializingBeanT implements BeanNameAware, InitializingBean, DisposableBean { public InitializingBeanT() { System.out.println("init無參構造 execute"); } @PostConstruct public void postConstruct() { System.out.println("@PostConstruct execute"); } @PreDestroy public void preDestroy() { System.out.println("@PreDestroy execute"); } @Override public void afterPropertiesSet() { System.out.println("InitializingBean afterPropertiesSet --> " + this.toString()); } @Override public void setBeanName(String name) { System.out.println("BeanNameAware : " + name); } @Override public void destroy() { System.out.println("destroy"); } } 測試代碼 @Test public void testLifeCycle() { AbstractApplicationContext applicationContext = new AnnotationConfigApplicationContext(ComponentScanD.class); applicationContext.close();// 這裏不關閉容器的話,註銷bean的方法會看不到打印 }
測試結果BeanFactoryPostProcessor bean com.vip.qc.postprocessor.InitializingBeanT
init無參構造 execute
BeanNameAware : initializingBeanT
BeanPostProcessor BeforeInitialization com.vip.qc.postprocessor.InitializingBeanT@15bb6bea
@PostConstruct execute
InitializingBean afterPropertiesSet –> com.vip.qc.postprocessor.InitializingBeanT@15bb6bea
BeanPostProcessor AfterInitialization com.vip.qc.postprocessor.InitializingBeanT@15bb6bea
@PreDestroy execute
destroy
菜瓜:實現什麼的不重要,接口才是爸爸呀,BeanFactory定義好了生命周期,下面的實現也只是實現罷了
水稻:哈哈,你說的對,一流的公司賣標準
菜瓜:這裏怎麼沒看到循環依賴的處理啊
水稻:是的。這裏的源碼我只截取了bean初始化完成之後的接口調用。循環依賴的處理在它前面。來來來,繼續剛
菜瓜:剛不了剛不了,你一下子搞這麼多玩意給我看,我哪看得完
水稻:您歇着,下次您什麼時候想了解我再給您說
總結
- BeanFactory已經定義了整個的生命周期,子類只是負責實現,demo演示也只是為了證實。我們更應該關注更上層的東西
- ApplicationContext是對容器更精細化的包裝,提供了更完善的功能
- FactoryBean是Spring擴展性的提現,可供用戶自己定義創建bean。擴展性提煉的很好
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!
※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
※別再煩惱如何寫文案,掌握八大原則!
※網頁設計最專業,超強功能平台可客製化