[quote="bennyparlo"] 没错,可以参考spring reference中的1段说明: 3.3. 属性,合作者,自动装配和依赖检查 3.3.1. 设置bean的属性和合作者 ................ 通常你可以信任Spring做了正确的事情。它会在BeanFactory装载的时候检查出错误,包括对不存在bean的引用和循环引用。它会尽可能晚地设置属性和解决依赖(比如创建那些需要的依赖),也就是在bean真正被创建的时候。这就意味着:就算一个BeanFactory被正确地装载,稍后当你请求一个bean的时候,如果创建那个bean或者它的依赖的时候出现了错误,这个BeanFactory也会抛出一个异常。比如,如果一个bean抛出一个异常作为缺少或非法属性的结果,这样的情况就会发生。这种潜在地推迟一些配置错误可见性的行为正是ApplicationContext默认预实例化singleton bean的原因。以前期的时间和内存为代价在beans真正需要之前创建它们,你就可以在ApplicationContext创建的时候找出配置错误,而不是在后来。如果你愿意,你也可以覆盖这种默认的行为,设置这些singleton bean为lazy-load(不是预实例化的)。 这里是翻译版的原文.应该可以对应你说的这段了.[/quote] 呵呵,把代码找出来,验证一下,这里涉及到一个预实例化的问题,也是BeanFactory和上下文使用的一个区别,也牵涉到一个bean定义属性lazy-init的使用: 我们记得在在上下文初始化的时候会通过refresh来完成 - 在AbstractApplicationContext中: [code] public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 这里是定位,读入,解析和注册bean定义的地方 refreshBeanFactory(); ....... try { ........ // 这里是对bean作预实例化的地方,也是lazy-init属性起作用的地方 beanFactory.preInstantiateSingletons(); // Last step: publish corresponding event. publishEvent(new ContextRefreshedEvent(this)); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. beanFactory.destroySingletons(); throw ex; } } } [/code] 在DefaultListableBeanFactory中, [code] public void preInstantiateSingletons() throws BeansException { if (logger.isInfoEnabled()) { logger.info("Pre-instantiating singletons in factory [" + this + "]"); } //这里迭代所有的bean定义 for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext();) { String beanName = (String) it.next(); if (!containsSingleton(beanName) && containsBeanDefinition(beanName)) { RootBeanDefinition bd = getMergedBeanDefinition(beanName, false); //预实例化只对singleton和lazy-init设为false的bean起作用 //而实际的预实例化就是在容器启动的过程就把依赖注入,而不是等到用户要求的时候 //调用getBean,和用户第一次要求的时候处理是一样的 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { Class beanClass = resolveBeanClass(bd, beanName); if (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass)) { getBean(FACTORY_BEAN_PREFIX + beanName); } else { getBean(beanName); } } } } } [/code] 而这个lazy-init的属性是在BeanDefinitionParserDelegate中设置的,但值得注意的是这里只作设置不做处理,处理要放到预实例化中去作。 [code] public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, BeanDefinition containingBean) { ........ //这里取得属性值,在bean定义文件中 String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); //如果是默认的值并且这个bean是单例,设为false if (DEFAULT_VALUE.equals(lazyInit) && bd.isSingleton()) { // Just apply default to singletons, as lazy-init has no meaning for prototypes. lazyInit = getDefaultLazyInit(); } //否则设为true bd.setLazyInit(TRUE_VALUE.equals(lazyInit)); ........ } [/code] 需要注意的是,getBean是BeanFactory的接口方法,而这里的调用都是在上下文中的。
Re: Spring源代码解析(一):IOC容器
最新推荐文章于 2022-12-17 15:30:26 发布