您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

Spring-IOC容器的介绍(附代码)

2024/4/28 21:17:43发布29次查看
本篇文章给大家带来的内容是关于spring-ioc容器的介绍(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
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容器的介绍(附代码)的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product