spring ioc容器对bean定义资源的载入是从refresh()函数开始的,refresh()是一个模板方法,refresh()方法的作用是:在创建ioc容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh之后使用的是新建立起来的ioc容器。refresh的作用类似于对ioc容器的重启,在新建立好的容器中对容器进行初始化,对bean定义资源进行载入
public void refresh() throws beansexception, illegalstateexception { object var1 = this.startupshutdownmonitor; synchronized(this.startupshutdownmonitor) { //调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识 this.preparerefresh(); //告诉子类启动refreshbeanfactory()方法,bean定义资源文件的载入从 //子类的refreshbeanfactory()方法启动 //这个bean的载入过程 包括对xml的解析和加载为beandefinitions 都是从this.obtainfreshbeanfactory()这里进入 configurablelistablebeanfactory beanfactory = this.obtainfreshbeanfactory(); /*这之后的代码都是注册容器的信息源和生命周期事件*/ //为beanfactory配置容器特性,例如类加载器、事件处理器等 this.preparebeanfactory(beanfactory); try { //为容器的某些子类指定特殊的beanpost事件处理器 this.postprocessbeanfactory(beanfactory); //调用所有注册的beanfactorypostprocessor的bean this.invokebeanfactorypostprocessors(beanfactory); //为beanfactory注册beanpost事件处理器. //beanpostprocessor是bean后置处理器,用于监听容器触发的事件 this.registerbeanpostprocessors(beanfactory); //初始化信息源,和国际化相关. this.initmessagesource(); //初始化容器事件传播器. this.initapplicationeventmulticaster(); //调用子类的某些特殊bean初始化方法 this.onrefresh(); //为事件传播器注册事件监听器. this.registerlisteners(); //初始化所有剩余的单态bean. this.finishbeanfactoryinitialization(beanfactory); //初始化容器的生命周期事件处理器,并发布容器的生命周期事件 this.finishrefresh(); } catch (beansexception var9) { if (this.logger.iswarnenabled()) { this.logger.warn(exception encountered during context initialization - cancelling refresh attempt: + var9); } //销毁以创建的单态bean this.destroybeans(); //取消refresh操作,重置容器的同步标识. this.cancelrefresh(var9); throw var9; } finally { this.resetcommoncaches(); } } }
abstractrefreshableapplicationcontext 类:
abstractrefreshableapplicationcontext中只定义了抽象的loadbeandefinitions方法,容器真正调用的是其子类abstractxmlapplicationcontext对该方法的实现
protected final void refreshbeanfactory() throws beansexception { //如果已经创建了beanfactory,则销毁并关闭beanfactory if (this.hasbeanfactory()) { this.destroybeans(); this.closebeanfactory(); } try { //创建了一个ioc容器 defaultlistablebeanfactory beanfactory = this.createbeanfactory(); beanfactory.setserializationid(this.getid()); /对ioc容器进行定制化,如设置启动参数,开启注解的自动装配等 this.customizebeanfactory(beanfactory); //调用载入bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadbeandefinitions方法,具体的实现调用子类容器 this.loadbeandefinitions(beanfactory); object var2 = this.beanfactorymonitor; synchronized(this.beanfactorymonitor) { this.beanfactory = beanfactory; } } catch (ioexception var5) { throw new applicationcontextexception(i/o error parsing bean definition source for + this.getdisplayname(), var5); } }
abstractxmlapplicationcontext 类:
protected void loadbeandefinitions(defaultlistablebeanfactory beanfactory) throws beansexception, ioexception { //创建xmlbeandefinitionreader,即创建bean读取器,并通过回调设置到容器中去,容器使用该读取器读取bean定义资源 xmlbeandefinitionreader beandefinitionreader = new xmlbeandefinitionreader(beanfactory); beandefinitionreader.setenvironment(this.getenvironment()); //为bean读取器设置spring资源加载器,abstractxmlapplicationcontext的 //祖先父类abstractapplicationcontext继承defaultresourceloader,因此,容器本身也是一个资源加载器 beandefinitionreader.setresourceloader(this); //为bean读取器设置sax xml解析器 beandefinitionreader.setentityresolver(new resourceentityresolver(this)); //当bean读取器读取bean定义的xml资源文件时,启用xml的校验机制 this.initbeandefinitionreader(beandefinitionreader); //bean读取器真正实现加载的方法 this.loadbeandefinitions(beandefinitionreader); } protected void initbeandefinitionreader(xmlbeandefinitionreader reader) { reader.setvalidating(this.validating); } protected void loadbeandefinitions(xmlbeandefinitionreader reader) throws beansexception, ioexception { resource[] configresources = this.getconfigresources(); if (configresources != null) { reader.loadbeandefinitions(configresources); } string[] configlocations = this.getconfiglocations(); if (configlocations != null) { reader.loadbeandefinitions(configlocations); } } @nullable protected resource[] getconfigresources() { return null; }
在其抽象父类abstractbeandefinitionreader中定义了载入过程
public int loadbeandefinitions(string location, @nullable set<resource> actualresources) throws beandefinitionstoreexception { //获取resourceloader resourceloader resourceloader = this.getresourceloader(); if (resourceloader == null) { throw new beandefinitionstoreexception(cannot import bean definitions from location [ + location + ]: no resourceloader available); } else { int loadcount; if (!(resourceloader instanceof resourcepatternresolver)) { //将指定位置的bean定义资源文件解析为spring ioc容器封装的资源 //加载多个指定位置的bean定义资源文件 完成具体的资源定位的工作 resource resource = resourceloader.getresource(location); //加载资源 开始我们的第二步操作 转换为beandefinition对象 loadcount = this.loadbeandefinitions((resource)resource); if (actualresources != null) { actualresources.add(resource); } if (this.logger.isdebugenabled()) { this.logger.debug(loaded + loadcount + bean definitions from location [ + location + ]); } return loadcount; } else { try { //将指定位置的bean定义资源文件解析为spring ioc容器封装的资源 //加载单个指定位置的bean定义资源文件 resource[] resources = ((resourcepatternresolver)resourceloader).getresources(location); //加载资源 开始我们的第二步操作 转换为beandefinition对象 loadcount = this.loadbeandefinitions(resources); if (actualresources != null) { resource[] var6 = resources; int var7 = resources.length; for(int var8 = 0; var8 beanclassname.length() && !this.readercontext.getregistry().isbeannameinuse(beanclassname)) { aliases.add(beanclassname); } } if(this.logger.isdebugenabled()) { this.logger.debug(neither xml 'id' nor 'name' specified - using generated bean name [ + beanname + ]); } } catch (exception var9) { this.error(var9.getmessage(), ele); return null; } } string[] aliasesarray = stringutils.tostringarray(aliases); return new beandefinitionholder(beandefinition, beanname, aliasesarray); } else { return null; } } //详细解析bean元素的地方 public abstractbeandefinition parsebeandefinitionelement(element ele, string beanname, beandefinition containingbean) { this.parsestate.push(new beanentry(beanname)); string classname = null; //是否包含class属性 if(ele.hasattribute(class)) { //获取class属性值 不做实例化,bean的实例化是在第一次获取bean的时候完成,这里只获取class的值 classname = ele.getattribute(class).trim(); } try { string parent = null; //如果<bean>元素中配置了parent属性,则获取parent属性的值 if(ele.hasattribute(parent)) { parent = ele.getattribute(parent); } //根据<bean>元素配置的class名称和parent属性值创建beandefinition //为载入bean定义信息做准备 abstractbeandefinition bd = this.createbeandefinition(classname, parent); //对当前的<bean>元素中配置的一些属性进行解析和设置,如配置的单态(singleton)属性等 this.parsebeandefinitionattributes(ele, beanname, containingbean, bd); //为<bean>元素解析的bean设置description信息 bd.setdescription(domutils.getchildelementvaluebytagname(ele, description_element)); bd.setdescription(domutils.getchildelementvaluebytagname(ele, description)); //对<bean>元素的meta(元信息)属性解析 this.parsemetaelements(ele, bd); //对<bean>元素的lookup-method属性解析 this.parselookupoverridesubelements(ele, bd.getmethodoverrides()); //对<bean>元素的replaced-method属性解析 this.parsereplacedmethodsubelements(ele, bd.getmethodoverrides()); //解析<bean>元素的构造方法设置 this.parseconstructorargelements(ele, bd); //解析<bean>元素的<property>设置 this.parsepropertyelements(ele, bd); //解析<bean>元素的qualifier属性 this.parsequalifierelements(ele, bd); bd.setresource(this.readercontext.getresource()); bd.setsource(this.extractsource(ele)); abstractbeandefinition var7 = bd; return var7; } catch (classnotfoundexception var13) { this.error(bean class [ + classname + ] not found, ele, var13); } catch (noclassdeffounderror var14) { this.error(class that bean class [ + classname + ] depends on not found, ele, var14); } catch (throwable var15) { this.error(unexpected failure during bean definition parsing, ele, var15); } finally { this.parsestate.pop(); } return null; }
通过对上述源码的分析,就会明白我们在spring配置文件中<bean>元素的中配置的属性就是通过该方法解析和设置到bean中去的。
注意:在解析<bean>元素过程中没有创建和实例化bean对象,只是创建了bean对象的定义类beandefinition,将<bean>元素中的配置信息设置到beandefinition中作为记录,当依赖注入时才使用这些记录信息创建和实例化具体的bean对象。
上面方法中一些对一些配置如元信息(meta)、qualifier等的解析,我们在spring中配置时使用的也不多,我们在使用spring的<bean>元素时,配置最多的是<property>属性。
调用beandefinitionreaderutils的registerbeandefinition方法向ioc容器注册解析的bean
protected void processbeandefinition(element ele, beandefinitionparserdelegate delegate) { beandefinitionholder bdholder = delegate.parsebeandefinitionelement(ele); if(bdholder != null) { //通过对document对象的解析和封装返回一个beandefinitionholder bdholder = delegate.decoratebeandefinitionifrequired(ele, bdholder); try { //通过这个holder来注册bean对象 beandefinitionreaderutils.registerbeandefinition(bdholder, this.getreadercontext().getregistry()); } catch (beandefinitionstoreexception var5) { this.getreadercontext().error(failed to register bean definition with name ' + bdholder.getbeanname() + ', ele, var5); } this.getreadercontext().firecomponentregistered(new beancomponentdefinition(bdholder)); } }
当调用beandefinitionreaderutils向ioc容器注册解析的beandefinition时,真正完成注册功能的是defaultlistablebeanfactory。
public static void registerbeandefinition(beandefinitionholder definitionholder, beandefinitionregistry registry) throws beandefinitionstoreexception { string beanname = definitionholder.getbeanname(); registry.registerbeandefinition(beanname, definitionholder.getbeandefinition()); string[] aliases = definitionholder.getaliases(); if(aliases != null) { string[] var4 = aliases; int var5 = aliases.length; for(int var6 = 0; var6 < var5; ++var6) { string alias = var4[var6]; registry.registeralias(beanname, alias); } } }
defaultlistablebeanfactory registerbeandefinition方法
//存储注册的俄beandefinition private final map<string, beandefinition> beandefinitionmap = new concurrenthashmap(256); //向ioc容器注册解析的beandefiniton public void registerbeandefinition(string beanname, beandefinition beandefinition) throws beandefinitionstoreexception { assert.hastext(beanname, bean name must not be empty); assert.notnull(beandefinition, beandefinition must not be null); //校验解析的beandefiniton if(beandefinition instanceof abstractbeandefinition) { try { ((abstractbeandefinition)beandefinition).validate(); } catch (beandefinitionvalidationexception var9) { throw new beandefinitionstoreexception(beandefinition.getresourcedescription(), beanname, validation of bean definition failed, var9); } } beandefinition oldbeandefinition = (beandefinition)this.beandefinitionmap.get(beanname); if(oldbeandefinition != null) { if(!this.isallowbeandefinitionoverriding()) { throw new beandefinitionstoreexception(beandefinition.getresourcedescription(), beanname, cannot register bean definition [ + beandefinition + ] for bean ' + beanname + ': there is already [ + oldbeandefinition + ] bound.); } if(oldbeandefinition.getrole() < beandefinition.getrole()) { if(this.logger.iswarnenabled()) { this.logger.warn(overriding user-defined bean definition for bean ' + beanname + ' with a framework-generated bean definition: replacing [ + oldbeandefinition + ] with [ + beandefinition + ]); } } else if(!beandefinition.equals(oldbeandefinition)) { if(this.logger.isinfoenabled()) { this.logger.info(overriding bean definition for bean ' + beanname + ' with a different definition: replacing [ + oldbeandefinition + ] with [ + beandefinition + ]); } } else if(this.logger.isdebugenabled()) { this.logger.debug(overriding bean definition for bean ' + beanname + ' with an equivalent definition: replacing [ + oldbeandefinition + ] with [ + beandefinition + ]); } this.beandefinitionmap.put(beanname, beandefinition); } else { if(this.hasbeancreationstarted()) { map var4 = this.beandefinitionmap; //注册的过程中需要线程同步,以保证数据的一致性 synchronized(this.beandefinitionmap) { //把bean存放到map中 this.beandefinitionmap.put(beanname, beandefinition); list<string> updateddefinitions = new arraylist(this.beandefinitionnames.size() + 1); updateddefinitions.addall(this.beandefinitionnames); updateddefinitions.add(beanname); this.beandefinitionnames = updateddefinitions; if(this.manualsingletonnames.contains(beanname)) { set<string> updatedsingletons = new linkedhashset(this.manualsingletonnames); updatedsingletons.remove(beanname); this.manualsingletonnames = updatedsingletons; } } } else { this.beandefinitionmap.put(beanname, beandefinition); this.beandefinitionnames.add(beanname); this.manualsingletonnames.remove(beanname); } this.frozenbeandefinitionnames = null; } if(oldbeandefinition != null || this.containssingleton(beanname)) { this.resetbeandefinition(beanname); } }
至此,bean定义资源文件中配置的bean被解析过后,已经注册到ioc容器中,被容器管理起来,真正完成了ioc容器初始化所做的全部工作。现 在ioc容器中已经建立了整个bean的配置信息,这些beandefinition信息已经可以使用,并且可以被检索,ioc容器的作用就是对这些注册的bean定义信息进行处理和维护。这些的注册的bean定义信息是ioc容器控制反转的基础,正是有了这些注册的数据,容器才可以进行依赖注入。
本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注的java视频教程栏目!
以上就是spring-ioc容器的介绍(附代码)的详细内容。
