【Spring】Bean的LifeCycle(生命週期)
菜瓜:水稻,上次說Bean的LifeCycle,還沒講完
水稻:啥?說人話?
菜瓜:spring,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。擴充套件性提煉的很好