spring容器IOC创建对象<二>

来源:互联网 发布:滤波算法 编辑:程序博客网 时间:2024/05/22 12:50

问题?spring是如何创建对象的?什么时候创建对象?有几种创建方式?测试对象是单例的还是多例的 ?对象的初始化和销毁?

下面的四大模块IOC的内容了!需要深刻理解


SpringIOC定义:把对象的创建、初始化、销毁等工作交给spring容器来做。由spring容器控制对象的生命周期。

先拷入核心jar包:点击打开下载链接

一、spring是如何创建对象的,有几种创建方式

   spring容器创建对象的方式

        1、默认是调用默认的构造函数

        2、利用静态工厂方法创建

            spring调用工厂方法产生对象,但是真正创建对象还是由程序员来完成的

        3、实例工厂方法

例子:

                 


简单的测试类:

package cn.itcast.sh.spring.ioc;public class HelloWord {public HelloWord(){System.out.println("构造方法实现了");}public void hello(){System.out.println("I'm a Ioc");}}


package cn.itcast.sh.spring.ioc;public class HelloWordFactory {public static HelloWord getInstance(){return new HelloWord();}}

package cn.itcast.sh.spring.ioc;public class HelloWordLocator {public static HelloWordLocator getInstance(){return new HelloWordLocator();}}



spring配置文件applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">                   <!-- id:标识符         class:相应的对象类,放入容器中         alias:别名,可写可不写,就是另外取一个名字         -->                    <!-- 这是第一种创建对象的方式:利用构造方法 ,一般都是采用这种方式来创建对象-->       <bean id="hello" class="cn.itcast.sh.spring.ioc.HelloWord"></bean>       <alias name="hello" alias="王三"/>              <!-- 这是第二种创建对象的方式:利用factory-method,静态工厂方法 -->       <bean id="helloFactory" class="cn.itcast.sh.spring.ioc.HelloWordFactory" factory-method="getInstance"></bean>              <!-- 这是第三种创建对象的方式:使用实例工厂方法实例化 -->        <bean id="heillLocator" class="cn.itcast.sh.spring.ioc.HelloWordLocator" factory-bean="heillLocator" factory-method="getInstance"></bean>        </beans>

测试对象的产生(注意:这里涉及到一个别名,但是用得不多,只是区别于不同的客户端去使用它来取名字,以不至于弄混):

package cn.itcast.sh.spring.ioc.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import cn.itcast.sh.spring.ioc.HelloWord;import cn.itcast.sh.spring.ioc.HelloWordFactory;public class IocTest {/** *  spring创建对象的两种方式 *    *///第一种:调用默认的构造方法进行创建@Testpublic void IocT1(){/** * 1.启动spring容器 * 2.从容器中拿出对象 * 3.然后由对象执行相应的操作 *  */ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");HelloWord helloWord = (HelloWord) context.getBean("王三");//取的是别名helloWord.hello();}//利用静态工厂来创建对象@Testpublic void IocT2(){ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");HelloWord factory = (HelloWord) context.getBean("helloFactory");factory.hello();}//利用实例工厂来创建对象@Testpublic void IocT3(){ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");HelloWordFactory factory = (HelloWordFactory) context.getBean("heillLocator");factory.getInstance();}}

结果如何来测一测


二、什么时候创建对象

     时间:这个又两个时间,一个是默认的在spring容器启动的时候,另外一个在getbean的时候创建对象(就是拿到配置文件中的标识符的时候创建对象)

两者有什么区别呢?

         1、在默认的情况下,启动spring容器创建对象

        2、在spring的配置文件bean中有一个属性lazy-init="default/true/false"

               (1)、如果lazy-init"default/false"在启动spring容器时创建对象

               (2)、如果lazy-init"true",context.getBean时才要创建对象

           意义:


                在第一种情况下可以在启动spring容器的时候,检查spring容器配置文件的正确性,如果再结合tomcat,

               如果spring容器不能正常启动,整个tomcat就不能正常启动。但是这样的缺点是把一些bean过早的放在了

                内存中,如果有数据,则对内存来是一个消耗,但是可以过早发现错误。


                在第二种情况下,可以减少内存的消耗,但是不容易发现错误

        在多例的情况下

            就是一种情况:在context.getBean时才创建对象

案例:

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">                <!--         1、在默认的情况下是,启动容器的时候,创建对象(这种方式可以及时发现错误)        2、 加上lazy-init="default":在getbean的时候创建对象(可以减少内存的浪费)         -->          <bean id="helloWhen" class="cn.itcast.sh.spring.when.HelloWord" lazy-init="true"></bean></beans>

测试类:

package cn.itcast.sh.spring.ioc.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import cn.itcast.sh.spring.when.HelloWord;public class IocWhen {/** * 检测对像是在什么时候创建的 * 1、是在启动spring容器 * 2、在调用方法的时候 */@Testpublic void test(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");System.out.println("先启动了spring容器");HelloWord helloWord = (HelloWord)applicationContext.getBean("helloWhen");helloWord.hello();}}

结果:

(1)如果是没有lazy-init="true",启动容器的时候创建对象


(2)如果lazy-init="true"




三、对象是单例的还是多例的 

     定义:意思就是,当多用户并发使用该对象的时候,创建该对象的时候,该对象是同一个吗?

      springbean中的scope

        1、由spring产生的bean默认是单例的

       2、可以在spring的配置文件中,scope的值进行修改="singleton/prototype/request/session/globalsession"

        3、如果spring的配置文件的scope"prototype",则产生的多例,并且是在getBean时才创建对象


案例:

package cn.itcast.sh.spring.scope;import java.util.ArrayList;import java.util.List;public class HelloWord {/** * 若产生的是默认单例的话,该list将会共享数据 * */private List<String> strings = new  ArrayList<String>();public List<String> getStrings() {return strings;}public void setStrings(List<String> strings) {this.strings = strings;}public HelloWord(){System.out.println("构造方法实现了-----");}public void hello(){System.out.println("I'm a Ioc");}}


applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">        <!-- 对象产生是默认(singleton)的单例,若要变成多例,需要配置属性scope='prototype':会使得产生对象的时间为getbean的时候,而不是spring容器启动的时候 -->          <bean id="helloScope" class="cn.itcast.sh.spring.scope.HelloWord" scope="prototype"></bean>       </beans>

测试类:

package cn.itcast.sh.spring.ioc.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import cn.itcast.sh.spring.scope.HelloWord;public class ScopeTest {@Testpublic void A(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");System.out.println("ssssssssssss");HelloWord helloWord = (HelloWord)applicationContext.getBean("helloScope");helloWord.getStrings().add("aaaa");HelloWord helloWord1 = (HelloWord)applicationContext.getBean("helloScope");helloWord1.getStrings().add("aaaa");System.out.println(helloWord.getStrings().size());System.out.println(helloWord);System.out.println(helloWord1);//结果显示是相同的对象//在这里可以说明产生的是单例对象(默认),单例有一个特点就是所属属性是一个共享的,不是很安全的问题,要注意这个问题。}}

结果:

(1)没有scope="prototype",那就是单例




(2)有scope="prototype"



若是单例的话,其对象类的资源会被共享,而多例就不一样了,只用各种对象。



四、对象的初始化和销毁

    首先我们要明白,对象创建了,会放在内存当中,只有关闭了spring或者关闭了该系统,对象才销毁,不占用内存,所以就要涉及到spring容器对象的生命周期:步骤为

       1spring容器创建对象

       2、执行init方法(初始化对象)

       3、调用自己的方法(对象的相应操作)

       4、当spring容器关闭的时候执行destroy方法(对象用完了,销毁)

   当scope"prototype"时,spring容器是否调用destroy方法?


案例:

对象类:

package cn.itcast.sh.spring.initdestory;import java.util.ArrayList;import java.util.List;public class HelloWord {public void init(){System.out.println("对象初始化了");}public void destroy(){System.out.println("对象销毁了");}public HelloWord(){System.out.println("构造方法实现了-----");}public void hello(){System.out.println("I'm a Ioc");}}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">                <!-- 构造方法先创建对象(spring容器来做),        init方法初始化对象(spring容器来做)             对象进行操作(客户端来做)                                     最后才是销毁,如果需要手动销毁,手动close             (spring容器来做,默认关闭容器才销毁对象,             销毁只针对单例,当scope为propert的时候,是不能销毁的)          -->          <bean id="helloInit" class="cn.itcast.sh.spring.initdestory.HelloWord"       init-method="init" destroy-method="destroy"></bean><!-- 这里填的方法是在对象类中填写的方法,一般是默认不填,自动执行 --></beans>

测试类:


package cn.itcast.sh.spring.ioc.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import cn.itcast.sh.spring.initdestory.HelloWord;public class InitDestoryTest {@Testpublic void A(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");HelloWord helloWord = (HelloWord)applicationContext.getBean("helloInit");helloWord.hello();//手动销毁对象//ClassPathXmlApplicationContext classPathXmlApplicationContext = (ClassPathXmlApplicationContext)context;//classPathXmlApplicationContext.close();}}


结果:




以上就是spring的IOC的四大模块详解了.


0 0