菜瓜:水稻,上次说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
{ 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
- 实验代码
-
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。扩展性提炼的很好