- 浏览: 233600 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
yxwdsq:
谢谢。用一下。
ibatis-2.3.4.726源码 -
wd200678:
还是不行,jar包获取外部的配置文件,用file代替class ...
spring3 jar 读取外部属性文件的配置方法 -
Tomzheng:
谢谢啊。用上了。
ibatis-2.3.4.726源码 -
农家书虫:
ibatis-2.3.4.726源码 -
marco727:
感谢感谢感谢博主,太难找了
ibatis-2.3.4.726源码
学习spring,找到一篇,http://www.blogjava.net/killme2008/archive/2007/04/20/112160.html,共享,虽然有点老,
spring IOC容器的实现,一开始我被复杂的接口和类所掩埋,看不清整体的思路和设计,踟蹰于代码丛林中,摸不清前进的方向。一开始我就决定只研读以xml文件做配置文件的XmlFactoryBean的具体实现为主要目标,渐渐地有了点感觉,用UML把spring中的bean工厂体系展现出来之后就更清晰了,让你不得不感叹设计的精巧和复杂。本文只是我个人对spring IOC实现的理解,如有错误,请不吝赐教,谢谢。
首先,需要理解的是spring容器中bean的生命周期,《spring in action》中的那张图是最好的解释,结合这张图和源码来解读spring中IOC的实现将非常容易理解。这张图完整展示了spring容器中一个bean从创建到销毁的整个生命周期。
1. 容器寻找Bean的定义信息并且将其实例化。
2.受用依赖注入,Spring按照Bean定义信息配置Bean的所有属性。
3.如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。
4.如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。
5.如果BeanPostProcessor和Bean关联,那么它们的postProcessBeforeInitialzation()方法将被调用。
6.如果Bean指定了init-method方法,它将被调用。
7.最后,如果有BeanPsotProcessor和Bean关联,那么它们的postProcessAfterInitialization()方法将被调用。
到这个时候,Bean已经可以被应用系统使用了,并且将被保留在Bean Factory中知道它不再需要。有两种方法可以把它从Bean Factory中删除掉。
1.如果Bean实现了DisposableBean接口,destory()方法被调用。
2.如果指定了订制的销毁方法,就调用这个方法。
下面我们将会看到,这些bean创建销毁的每个阶段是如何在源码中实现的。
再看看spring中bean工厂的完整体系,比较复杂,不过我们只需要关注其中的几个核心工厂。
(看不清楚,请下载图片来看,比较清晰)
这些工厂类没有在同一个包内,分布在org.springframework.beans以及它的子包内,把它们放在一起就看的比较清楚了。我们需要关注的是这么两个类:
AbstractBeanFactory作为BeanFactory接口的抽象实现类,是其他工厂类的父类,提供了bean的singlton缓存、singleton/prototype的决定、bean的别名以及bean和它的子类bean的定义合并(bean definition merging for child bean definitions)和销毁。这里有3个重载的getBean方法(实现BeanFactory定义的getBean方法),我们关注下最主要的这个方法:
当你调用getBean获取一个bean的时候,spring首先查找单例缓存中是否已经有这个bean,有的话直接返回(首先会判断是否已经创建),如果没有,spring就开始创建这个bean:首先获取bean的定义(BeanDefinition),检测bean是否定义在父工厂中,有的话调用父工厂的getBean方法;没有就检测bean是singleton还是prototype,如果是singleton就是创建bean并加入缓存以便下次直接调用,如果是prototype,就在每次调用时重新创建一个bean实例。注意createBean(beanName, mergedBeanDefinition, args); 这个方法,这是创建bean的核心方法,并且是一个abstract方法,将被子类实现。
看看是如何获取bean的定义的,
调用重载的getMergedBeanDefinition合并父工厂和子工厂中的bean定义,注意getBeanDefinition(beanName),这是一个抽象方法,延迟到子类实现以便提供获取bean定义的具体方法,这个方法和 createBean 一样都是template method模式的应用。看看它们的定义:
基本了解了AbstractBeanFactory 后,我们来看看它的子类的AbstractAutowireCapableBeanFactory ,这个类实现了createBean() ,在这个方法中我们将看到与上面bean的生命周期图对应的bean的创建过程,英文注释已经非常清楚:
通过instanceof操作符来判断bean是否实现了用于生命周期回调的接口,然后调用相应的回调方法,可以看到spring充分实践了针对接口编程的原则,虽然很夸张的一个方法一个接口的地步,不过这些接口也是作为mark interface用于标记回调。结合上面的生命周期图看这段代码将很好理解。有了bean的创建方法,那么如何获取bean在配置文件中的定义信息呢?也就是在哪里实现了 getBeanDefinition方法呢?答案就在AbstractAutowireCapableBeanFactory 的子类DefaultListableBeanFactory中。
DefaultListableBeanFactory 不仅继承了AbstractAutowireCapableBeanFactory ,还实现了BeanDefinitionRegistry和ConfigurableListableBeanFactory接口。其中ConfigurableListableBeanFactory接口是定义了分析和修改bean定义信息的回调方法,暂时不去管它。看看BeanDefinitionRegistry接口:
一系列用于获取bean定义信息的方法,这个接口我们将在后面的代码中看到,作为一个mark inteface。注意咯,这个接口中非常关键的一个方法就是registerBeanDefinition,这个方法用于向bean工厂注册解析的每个bean定义,我们将在xml文件的解析的环节看到调用这个方法注册bean定义信息。
DefaultListableBeanFactory实现了BeanDefinitionRegistry 接口,可以看到它实现了关键的registerBeanDefinition用于将bean的定义注册到工厂类中,其中维护了一个Map用于存储bean的定义信息:
beanDefinitionMap就是我们存储工厂类中注册的bean的信息,用bean name做为key:
模板方法用于提供bean定义信息给getBean方法用于创建bean实例。getBeanDefinition的从beanDefinitionMap 查找bean定义即可:
看到了这里是不是觉的有点糊涂,我还是建议有兴趣地找来spring1.2的源码来看看就很清晰了,充分利用eclipse的F3跳转结合上面的那张UML图。
OK,有了注册bean定义信息的方法(registerBeanDefinition),有了获取bean定义信息的方法(getBeanDefinition ),有了创建bean的方法(createBean),那么在哪里调用这些方法呢?createBean我们已经知道是在BeanFactory的getBean方法时调用,getBeanDefinition 又是在creatBean时调用用于获取bean的定义信息,那么注册bean定义信息的方法肯定是在xml文件解析阶段被调用。
XmlBeanFactory继承DefaultListableBeanFactory ,没有定义新的方法,只是有两个重载的构造函数:
初始化XmlBeanFactory时调用XmlBeanDefinitionReader读取xml配置文件,而XmlBeanDefinitionReader的loadBeanDefinitions方法,载入xml文件并且调用XmlBeanDefinitionParser 解析xml文件同时注册bean定义信息到bean工厂,这几个类的协作以及它们继承体系也非常清晰,在此不再详述(累啊),XmlBeanDefinitionParser是一个接口,具体的实现类是org.springframework.beans.factory.xml.DefaultXmlBeanDefinitionParser,我们关注的就是它是怎么注册bean信息到bean工厂的:
注意这里的beanFactory是BeanDefinitionRegistry类型 ,DefaultListableBeanFactory实现了这个接口。
更多内容,比如spring是怎么把bean的属性注入的?答案在BeanWrapperImpl中的一系列setPropertyXXX方法。BeanFactory是如何实例化bean的呢?具体展开请看org.springframework.beans.factory.support.InstantiationStrategy 接口,一个典型的策略模式的应用,两个实现类:SimpleInstantiationStrategy和CglibSubclassingInstantiationStrategy。我们知道spring有3种注入方式:setter、构造函数以及Method Inject。这里的CglibSubclassingInstantiationStrategy使用cglib库用于实现method inject。这样一篇小文容不下这么多内容,还是有兴趣的自己找源码读读。
写到这里,我对自己的文字表达能力产生怀疑,我能不能把这些所有的信息都说清楚呢?感觉很不满意,将就吧,也算是自己的学习总结。
读spring源码这段时间,最深的几点体会:
1)单元测试非常重要,充分感受到了单元测试作为项目文档的优势。看不懂一个类,找到这个类的测试类就OK!
2)针对接口编程的原则,spring处处体现了这个原则,繁多的接口带来的是松耦合、高内聚并且易于扩展的架构,但也带来了一定的理解难度。作为通用型框架也许需要这么考虑,在实际项目中的取舍还是要自己把握。
3)设计模式的使用,spring中应用了很多模式,比如template method,比如strategy和factory method、visitor、singleton等,简直是一本模式实践的良好教材。
spring IOC容器的实现,一开始我被复杂的接口和类所掩埋,看不清整体的思路和设计,踟蹰于代码丛林中,摸不清前进的方向。一开始我就决定只研读以xml文件做配置文件的XmlFactoryBean的具体实现为主要目标,渐渐地有了点感觉,用UML把spring中的bean工厂体系展现出来之后就更清晰了,让你不得不感叹设计的精巧和复杂。本文只是我个人对spring IOC实现的理解,如有错误,请不吝赐教,谢谢。
首先,需要理解的是spring容器中bean的生命周期,《spring in action》中的那张图是最好的解释,结合这张图和源码来解读spring中IOC的实现将非常容易理解。这张图完整展示了spring容器中一个bean从创建到销毁的整个生命周期。
1. 容器寻找Bean的定义信息并且将其实例化。
2.受用依赖注入,Spring按照Bean定义信息配置Bean的所有属性。
3.如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。
4.如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。
5.如果BeanPostProcessor和Bean关联,那么它们的postProcessBeforeInitialzation()方法将被调用。
6.如果Bean指定了init-method方法,它将被调用。
7.最后,如果有BeanPsotProcessor和Bean关联,那么它们的postProcessAfterInitialization()方法将被调用。
到这个时候,Bean已经可以被应用系统使用了,并且将被保留在Bean Factory中知道它不再需要。有两种方法可以把它从Bean Factory中删除掉。
1.如果Bean实现了DisposableBean接口,destory()方法被调用。
2.如果指定了订制的销毁方法,就调用这个方法。
下面我们将会看到,这些bean创建销毁的每个阶段是如何在源码中实现的。
再看看spring中bean工厂的完整体系,比较复杂,不过我们只需要关注其中的几个核心工厂。
(看不清楚,请下载图片来看,比较清晰)
这些工厂类没有在同一个包内,分布在org.springframework.beans以及它的子包内,把它们放在一起就看的比较清楚了。我们需要关注的是这么两个类:
org.springframework.beans.factory.support.AbstractBeanFactory org.springframework.beans.factory.support.DefaultListableBeanFactory以及接口:
org.springframework.beans.factory.support.BeanDefinitionRegistry
AbstractBeanFactory作为BeanFactory接口的抽象实现类,是其他工厂类的父类,提供了bean的singlton缓存、singleton/prototype的决定、bean的别名以及bean和它的子类bean的定义合并(bean definition merging for child bean definitions)和销毁。这里有3个重载的getBean方法(实现BeanFactory定义的getBean方法),我们关注下最主要的这个方法:
public Object getBean(String name, Class requiredType, Object[] args) throws BeansException { String beanName = transformedBeanName(name); Object bean = null; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = null; //从单例缓存中获取 synchronized (this.singletonCache) { sharedInstance = this.singletonCache.get(beanName); } if (sharedInstance != null) { if (isSingletonCurrentlyInCreation(beanName)) { if (logger.isDebugEnabled()) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } } else { if (logger.isDebugEnabled()) { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForSharedInstance(name, sharedInstance); } else { // Fail if we're already creating this singleton instance: // We're assumably within a circular reference. if (isSingletonCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. //检测bean是否定义在父工厂 if (getParentBeanFactory() != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. if (getParentBeanFactory() instanceof AbstractBeanFactory) { // Delegation to parent with args only possible for AbstractBeanFactory. return ((AbstractBeanFactory) getParentBeanFactory()).getBean(name, requiredType, args); } else if (args == null) { // No args -> delegate to standard getBean method. return getParentBeanFactory().getBean(name, requiredType); } else { throw new NoSuchBeanDefinitionException(beanName, "Cannot delegate to parent BeanFactory because it does not supported passed-in arguments"); } } //获取BeanDefinition RootBeanDefinition mergedBeanDefinition = getMergedBeanDefinition(beanName, false); checkMergedBeanDefinition(mergedBeanDefinition, beanName, requiredType, args); // Create bean instance. //创建bean,如果为为singleton if (mergedBeanDefinition.isSingleton()) { synchronized (this.singletonCache) { // Re-check singleton cache within synchronized block. sharedInstance = this.singletonCache.get(beanName); if (sharedInstance == null) { if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } this.currentlyInCreation.add(beanName); try { sharedInstance = createBean(beanName, mergedBeanDefinition, args); //加进单例缓存 addSingleton(beanName, sharedInstance); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroyDisposableBean(beanName); throw ex; } finally { this.currentlyInCreation.remove(beanName); } } } bean = getObjectForSharedInstance(name, sharedInstance); } //如果是prototype else { // It's a prototype -> create a new instance. bean = createBean(beanName, mergedBeanDefinition, args); } } // Check if required type matches the type of the actual bean instance. if (requiredType != null && !requiredType.isAssignableFrom(bean.getClass())) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return bean; }
当你调用getBean获取一个bean的时候,spring首先查找单例缓存中是否已经有这个bean,有的话直接返回(首先会判断是否已经创建),如果没有,spring就开始创建这个bean:首先获取bean的定义(BeanDefinition),检测bean是否定义在父工厂中,有的话调用父工厂的getBean方法;没有就检测bean是singleton还是prototype,如果是singleton就是创建bean并加入缓存以便下次直接调用,如果是prototype,就在每次调用时重新创建一个bean实例。注意createBean(beanName, mergedBeanDefinition, args); 这个方法,这是创建bean的核心方法,并且是一个abstract方法,将被子类实现。
看看是如何获取bean的定义的,
protected RootBeanDefinition getMergedBeanDefinition(String name, boolean includingAncestors) throws BeansException { String beanName = transformedBeanName(name); // Efficiently check whether bean definition exists in this factory. if (includingAncestors && !containsBeanDefinition(beanName) && getParentBeanFactory() instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName, true); } // Resolve merged bean definition locally. return getMergedBeanDefinition(beanName, getBeanDefinition(beanName)); }
调用重载的getMergedBeanDefinition合并父工厂和子工厂中的bean定义,注意getBeanDefinition(beanName),这是一个抽象方法,延迟到子类实现以便提供获取bean定义的具体方法,这个方法和 createBean 一样都是template method模式的应用。看看它们的定义:
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException; protected abstract Object createBean( String beanName, RootBeanDefinition mergedBeanDefinition, Object[] args) throws BeanCreationException;
基本了解了AbstractBeanFactory 后,我们来看看它的子类的AbstractAutowireCapableBeanFactory ,这个类实现了createBean() ,在这个方法中我们将看到与上面bean的生命周期图对应的bean的创建过程,英文注释已经非常清楚:
protected Object createBean(String beanName, RootBeanDefinition mergedBeanDefinition, Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "' with merged definition [" + mergedBeanDefinition + "]"); } Object bean = null; // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. if (mergedBeanDefinition.hasBeanClass()) { bean = applyBeanPostProcessorsBeforeInstantiation(mergedBeanDefinition.getBeanClass(), beanName); if (bean != null) { return bean; } } // Guarantee initialization of beans that the current one depends on. if (mergedBeanDefinition.getDependsOn() != null) { for (int i = 0; i < mergedBeanDefinition.getDependsOn().length; i++) { getBean(mergedBeanDefinition.getDependsOn()[i]); } } BeanWrapper instanceWrapper = null; Object originalBean = null; String errorMessage = null; try { // Instantiate the bean. errorMessage = "Instantiation of bean failed"; if (mergedBeanDefinition.getFactoryMethodName() != null) { instanceWrapper = instantiateUsingFactoryMethod(beanName, mergedBeanDefinition, args); } else if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mergedBeanDefinition.hasConstructorArgumentValues() ) { instanceWrapper = autowireConstructor(beanName, mergedBeanDefinition); } else { // No special handling: simply use no-arg constructor. instanceWrapper = instantiateBean(beanName, mergedBeanDefinition); } bean = instanceWrapper.getWrappedInstance(); // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. if (isAllowCircularReferences() && isSingletonCurrentlyInCreation(beanName)) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean with name '" + beanName + "' to allow for resolving potential circular references"); } addSingleton(beanName, bean); } // Initialize the bean instance. errorMessage = "Initialization of bean failed"; populateBean(beanName, mergedBeanDefinition, instanceWrapper); if (bean instanceof BeanNameAware) { if (logger.isDebugEnabled()) { logger.debug("Invoking setBeanName on BeanNameAware bean '" + beanName + "'"); } ((BeanNameAware) bean).setBeanName(beanName); } if (bean instanceof BeanFactoryAware) { if (logger.isDebugEnabled()) { logger.debug("Invoking setBeanFactory on BeanFactoryAware bean '" + beanName + "'"); } ((BeanFactoryAware) bean).setBeanFactory(this); } originalBean = bean; bean = applyBeanPostProcessorsBeforeInitialization(bean, beanName); invokeInitMethods(beanName, bean, mergedBeanDefinition); bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException( mergedBeanDefinition.getResourceDescription(), beanName, errorMessage, ex); } // Register bean as disposable, and also as dependent on specified "dependsOn" beans. registerDisposableBeanIfNecessary(beanName, originalBean, mergedBeanDefinition); return bean; }
通过instanceof操作符来判断bean是否实现了用于生命周期回调的接口,然后调用相应的回调方法,可以看到spring充分实践了针对接口编程的原则,虽然很夸张的一个方法一个接口的地步,不过这些接口也是作为mark interface用于标记回调。结合上面的生命周期图看这段代码将很好理解。有了bean的创建方法,那么如何获取bean在配置文件中的定义信息呢?也就是在哪里实现了 getBeanDefinition方法呢?答案就在AbstractAutowireCapableBeanFactory 的子类DefaultListableBeanFactory中。
DefaultListableBeanFactory 不仅继承了AbstractAutowireCapableBeanFactory ,还实现了BeanDefinitionRegistry和ConfigurableListableBeanFactory接口。其中ConfigurableListableBeanFactory接口是定义了分析和修改bean定义信息的回调方法,暂时不去管它。看看BeanDefinitionRegistry接口:
public interface BeanDefinitionRegistry { int getBeanDefinitionCount(); String[] getBeanDefinitionNames(); BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; String[] getAliases(String beanName) throws NoSuchBeanDefinitionException; void registerAlias(String beanName, String alias) throws BeansException; void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeansException; ...... }
一系列用于获取bean定义信息的方法,这个接口我们将在后面的代码中看到,作为一个mark inteface。注意咯,这个接口中非常关键的一个方法就是registerBeanDefinition,这个方法用于向bean工厂注册解析的每个bean定义,我们将在xml文件的解析的环节看到调用这个方法注册bean定义信息。
DefaultListableBeanFactory实现了BeanDefinitionRegistry 接口,可以看到它实现了关键的registerBeanDefinition用于将bean的定义注册到工厂类中,其中维护了一个Map用于存储bean的定义信息:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "Bean definition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } Object oldBeanDefinition = this.beanDefinitionMap.get(beanName); if (oldBeanDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': there's already [" + oldBeanDefinition + "] bound"); } else { if (logger.isInfoEnabled()) { logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } } else { this.beanDefinitionNames.add(beanName); } this.beanDefinitionMap.put(beanName, beanDefinition); // Remove corresponding bean from singleton cache, if any. // Shouldn't usually be necessary, rather just meant for overriding // a context's default beans (e.g. the default StaticMessageSource // in a StaticApplicationContext). removeSingleton(beanName); }
beanDefinitionMap就是我们存储工厂类中注册的bean的信息,用bean name做为key:
/** Map of bean definition objects, keyed by bean name */ private final Map beanDefinitionMap = new HashMap(); DefaultListableBeanFactory 重写了 protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
模板方法用于提供bean定义信息给getBean方法用于创建bean实例。getBeanDefinition的从beanDefinitionMap 查找bean定义即可:
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { BeanDefinition bd = (BeanDefinition) this.beanDefinitionMap.get(beanName); if (bd == null) { if (logger.isDebugEnabled()) { logger.debug("No bean named '" + beanName + "' found in " + toString()); } throw new NoSuchBeanDefinitionException(beanName); } return bd; }
看到了这里是不是觉的有点糊涂,我还是建议有兴趣地找来spring1.2的源码来看看就很清晰了,充分利用eclipse的F3跳转结合上面的那张UML图。
OK,有了注册bean定义信息的方法(registerBeanDefinition),有了获取bean定义信息的方法(getBeanDefinition ),有了创建bean的方法(createBean),那么在哪里调用这些方法呢?createBean我们已经知道是在BeanFactory的getBean方法时调用,getBeanDefinition 又是在creatBean时调用用于获取bean的定义信息,那么注册bean定义信息的方法肯定是在xml文件解析阶段被调用。
XmlBeanFactory继承DefaultListableBeanFactory ,没有定义新的方法,只是有两个重载的构造函数:
public class XmlBeanFactory extends DefaultListableBeanFactory { private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); public XmlBeanFactory(Resource resource) throws BeansException { this(resource, null); } public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); this.reader.loadBeanDefinitions(resource); } }
初始化XmlBeanFactory时调用XmlBeanDefinitionReader读取xml配置文件,而XmlBeanDefinitionReader的loadBeanDefinitions方法,载入xml文件并且调用XmlBeanDefinitionParser 解析xml文件同时注册bean定义信息到bean工厂,这几个类的协作以及它们继承体系也非常清晰,在此不再详述(累啊),XmlBeanDefinitionParser是一个接口,具体的实现类是org.springframework.beans.factory.xml.DefaultXmlBeanDefinitionParser,我们关注的就是它是怎么注册bean信息到bean工厂的:
protected int parseBeanDefinitions(Element root) throws BeanDefinitionStoreException { if (IMPORT_ELEMENT.equals(node.getNodeName())) { importBeanDefinitionResource(ele); } else if (ALIAS_ELEMENT.equals(node.getNodeName())) { String name = ele.getAttribute(NAME_ATTRIBUTE); String alias = ele.getAttribute(ALIAS_ATTRIBUTE); this.beanDefinitionReader.getBeanFactory().registerAlias(name, alias); } else if (BEAN_ELEMENT.equals(node.getNodeName())) { beanDefinitionCount++; BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele, false); //关键代码,调用工具类将bean定义注册到beanFactory BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.beanDefinitionReader.getBeanFactory()); } } 工具类BeanDefinitionReaderUtils中的注册方法: public static void registerBeanDefinition( BeanDefinitionHolder bdHolder, BeanDefinitionRegistry beanFactory) throws BeansException { // Register bean definition under primary name.,注册bean beanFactory.registerBeanDefinition(bdHolder.getBeanName(), bdHolder.getBeanDefinition()); // Register aliases for bean name, if any.,注册别名 if (bdHolder.getAliases() != null) { for (int i = 0; i < bdHolder.getAliases().length; i++) { beanFactory.registerAlias(bdHolder.getBeanName(), bdHolder.getAliases()[i]); } } }
注意这里的beanFactory是BeanDefinitionRegistry类型 ,DefaultListableBeanFactory实现了这个接口。
更多内容,比如spring是怎么把bean的属性注入的?答案在BeanWrapperImpl中的一系列setPropertyXXX方法。BeanFactory是如何实例化bean的呢?具体展开请看org.springframework.beans.factory.support.InstantiationStrategy 接口,一个典型的策略模式的应用,两个实现类:SimpleInstantiationStrategy和CglibSubclassingInstantiationStrategy。我们知道spring有3种注入方式:setter、构造函数以及Method Inject。这里的CglibSubclassingInstantiationStrategy使用cglib库用于实现method inject。这样一篇小文容不下这么多内容,还是有兴趣的自己找源码读读。
写到这里,我对自己的文字表达能力产生怀疑,我能不能把这些所有的信息都说清楚呢?感觉很不满意,将就吧,也算是自己的学习总结。
读spring源码这段时间,最深的几点体会:
1)单元测试非常重要,充分感受到了单元测试作为项目文档的优势。看不懂一个类,找到这个类的测试类就OK!
2)针对接口编程的原则,spring处处体现了这个原则,繁多的接口带来的是松耦合、高内聚并且易于扩展的架构,但也带来了一定的理解难度。作为通用型框架也许需要这么考虑,在实际项目中的取舍还是要自己把握。
3)设计模式的使用,spring中应用了很多模式,比如template method,比如strategy和factory method、visitor、singleton等,简直是一本模式实践的良好教材。
发表评论
-
spring Could not resolve placeholder 的可能解决方式
2011-10-25 16:49 9128spring 读取properties文件,遇到C ... -
spring3 jar 读取外部属性文件的配置方法
2011-10-25 16:37 4413使用maven-jar插件,将项目打成jar包,将 ... -
spring 扫描jar maven 打包
2011-08-11 21:19 8364Spring注解自动扫描Jar中的类,以前在eclipse下, ... -
spring学习记录
2010-12-29 15:52 10111、spring IOC容器实现探讨 http://www.b ... -
spring源码svn
2010-12-28 17:41 2142spring源码svn https://src.springs ...
相关推荐
《Spring IOC容器实现分析》 在Java开发领域,Spring框架无疑是使用最为广泛的轻量级框架之一,其中的核心组件就是IOC(Inversion of Control)容器。本文将深入剖析Spring的IOC容器,理解其工作原理和重要功能,以...
本文将从实现的角度,通过对外部接口、内部实现、组成部分和执行过程四个角度深入剖析Spring IoC容器的结构。 首先,Spring IoC容器的外部接口主要包括`ApplicationContext`和`BeanFactory`。`BeanFactory`是IoC...
### Spring IOC容器实现分析 #### 一、Spring IOC容器概览 Spring框架作为一款轻量级的开源框架,其核心之一便是IOC(Inversion of Control)容器。该容器的主要功能在于管理和控制对象间的依赖关系,使得开发人员...
spring Ioc容器配置 IOC容器数据源配置 <!-- 配置数据源 --> destroy-method="close"> <value>org.gjt.mm.mysql.Driver <value>jdbc:mysql://localhost:3306/demo <value>root ...
Spring Ioc容器是整个Spring框架的基石,它负责创建、配置和管理对象。容器通过读取XML、Java注解或Java配置类等方式,获取对象的定义信息,然后根据这些信息实例化对象并进行依赖注入。 **三、依赖注入(DI,...
以下是Spring IOC容器的主要知识点: 1. **Bean的定义**:在Spring中,业务对象被称为Bean。Bean定义包含了创建和管理Bean的所有信息,如类名、属性值、依赖关系等,通常通过XML、注解或Java配置来定义。 2. **...
本项目"手写一个SpringIoc容器"旨在模仿Spring的IOC(Inversion of Control,控制反转)功能,帮助开发者深入理解Spring的工作原理,提升对依赖注入(Dependency Injection)模式的认识。 在实现自定义的Spring IOC...
### Spring IoC容器部署实现详解 #### 一、Spring IoC容器概述 Spring框架的核心特性之一就是Inversion of Control(IoC),也被称为Dependency Injection(DI)。IoC容器是Spring框架的重要组成部分,它负责管理...
现在,我们将深入探讨如何模拟Spring的IoC容器实现注解自动装配。 首先,我们需要理解IoC容器的基本工作原理。IoC容器是通过扫描应用程序上下文来发现所有需要管理的bean,并根据bean定义来创建和初始化这些bean。...
自己动手实现Spring IoC容器, 写Spring IOC容器.wps写Spring IOC容器.wps写Spring IOC容器.wps
`BeanFactory`是最基本的IoC容器实现,它主要负责创建和管理bean的生命周期。BeanFactory提供了一系列基础方法,例如获取bean、判断bean的存在性、判断bean是否为单例等。它是所有Spring容器的基类,为其他容器提供...
Spring IOC 容器启动流程分析 Spring IOC 容器是 Java 企业级应用程序的核心组件之一,它提供了一个统一的依赖注入机制,使得应用程序的组件之间能够松耦合。Spring IOC 容器的启动流程是整个 Spring 框架的核心...
Spring IoC容器通过XML配置或注解实现了对象的创建、管理和依赖注入,极大地简化了Java应用的复杂性。理解并熟练运用Spring IoC,能够帮助开发者构建更灵活、易于测试和维护的系统。在实际开发中,还可以结合@...
IoC(Inversion of Control)是 Spring 框架中的一种设计模式,它的主要思想是将对象的创建和管理交给容器,从而解耦合对象之间的依赖关系。今天,我们将详细解析 IoC 的优点和缺点。 优点 1. 简化对象的创建:IoC ...
总的来说,Spring框架通过其IoC容器实现了对象的管理和依赖注入,带来了诸多好处,同时Eclipse作为强大的开发工具,为创建和管理Spring Web应用提供了便利。了解和掌握这些知识,对于提升Java开发效率和代码质量具有...
**Spring IOC 容器应用实例** Spring 框架的核心组件之一是 Inversion of Control (IoC) 容器,也常被称为依赖注入(Dependency Injection)容器。IoC 是一种设计模式,它将对象的创建和管理从应用程序的业务逻辑中...
在本教程中,我们将深入探讨如何通过XML配置在Spring IOC容器中实现依赖注入。 首先,我们需要了解Spring的IOC容器。IOC容器是Spring的核心,它负责管理对象的生命周期和对象间的依赖关系。容器通过读取XML配置文件...
本文将深入探讨如何实现一个简单的Spring IOC容器,以及涉及的主要知识点。 首先,控制反转是一种设计模式,它将对象的创建和管理从对象本身转移到一个外部容器,即IOC容器。Spring的IOC容器通过读取配置文件(如...
IoC容器是Spring实现这一理念的重要工具,它负责管理对象的生命周期和对象之间的依赖关系。本教程将通过一个简单的模拟来帮助你快速理解Spring的IoC容器。 首先,我们要了解IoC的基本概念。IoC是指应用程序的控制...