问题?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创建对象的两种方式
	 *
	 */

	//第一种:调用默认的构造方法进行创建
	@Test
	public void IocT1(){
		/**
		 * 1.启动spring容器
		 * 2.从容器中拿出对象
		 * 3.然后由对象执行相应的操作
		 *
		 */
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		HelloWord helloWord = (HelloWord) context.getBean("王三");//取的是别名
		helloWord.hello();
	}

	//利用静态工厂来创建对象
	@Test
	public void IocT2(){
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		HelloWord factory = (HelloWord) context.getBean("helloFactory");
		factory.hello();
	}

	//利用实例工厂来创建对象
		@Test
		public 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、在调用方法的时候
	 */
	@Test
	public 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"

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

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

spring的bean中的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 {
	@Test
	public 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容器对象的生命周期:步骤为

1、spring容器创建对象

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 {
	@Test
	public void A(){
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		HelloWord helloWord = (HelloWord)applicationContext.getBean("helloInit");
		helloWord.hello();

		//手动销毁对象
//		ClassPathXmlApplicationContext classPathXmlApplicationContext = (ClassPathXmlApplicationContext)context;
//		classPathXmlApplicationContext.close();
		}
}

结果:

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

spring容器IOC创建对象<二>的更多相关文章

  1. spring容器IOC创建对象<三>

    问题?Spring的DI讲解.DI有几种注入方式.一.spring的DI:依赖注入给属性赋值DI定义:一个对象类的属性可以使用springDI(依赖注入)来进行赋值,但是并不是所有的类属性都适合spr ...

  2. spring容器IOC原理解析

    原理简单介绍: Spring容器的原理,其实就是通过解析xml文件,或取到用户配置的bean,然后通过反射将这些bean挨个放到集合中,然后对外提供一个getBean()方法,以便我们获得这些bean ...

  3. 菜鸟学SSH(十三)——Spring容器IOC解析及简单实现

    最近一段时间,“容器”两个字一直萦绕在我的耳边,甚至是吃饭.睡觉的时候都在我脑子里蹦来蹦去的.随着这些天一次次的交流.讨论,对于容器的理解也逐渐加深.理论上的东西终归要落实到实践,今天就借助Sprin ...

  4. Spring容器IOC解析及简单实现(转)

    文章转自http://blog.csdn.net/liushuijinger/article/details/35978965

  5. Spring详解(二)------IOC控制反转

    我相信提到 Spring,很多人会脱口而出IOC(控制反转).DI(依赖注入).AOP等等概念,这些概念也是面试官经常问到的知识点.那么这篇博客我们就来详细的讲解 IOC控制反转. ps:本篇博客源码 ...

  6. Spring_01 spring容器、控制反转(IOC)、依赖注入(DI)

    目录 1 什么是spring框架 2 spring框架的特点 3 spring容器 3.1 什么是spring容器 3.2 spring容器创建对象的编程步骤 3.4 spring容器创建对象的方式 ...

  7. Spring实战(二)Spring容器和bean的生命周期

    引入问题: 在XML配置文件中配置bean后,这些文件又是如何被加载的?它们被加载到哪里去了? Spring容器——框架核心 1.什么是Spring容器?它的功能是什么? 在基于Spring的应用中, ...

  8. 菜鸟学SSH(十四)——Spring容器AOP的实现原理——动态代理

    之前写了一篇关于IOC的博客——<Spring容器IOC解析及简单实现>,今天再来聊聊AOP.大家都知道Spring的两大特性是IOC和AOP,换句话说,容器的两大特性就是IOC和AOP. ...

  9. spring容器和上下文的理解

    spring容器和上下文的理解 spring框架现在使用的很多,这说明有其独特之处----依赖注入,很简单的四个字,在我们需要对象的时候,spring就可以给我们提供所需要的对象,对象的创建.销毁.管 ...

随机推荐

  1. 【HTML5】特性

    HTML5 建立的一些规则: 新特性应该基于 HTML.CSS.DOM 以及 JavaScript. 减少对外部插件的需求(比如 Flash) 更优秀的错误处理 更多取代脚本的标记 HTML5 应该独 ...

  2. map与mapPartitions

    区别在于sc.map是将RDD下的所有行数据统计处理.而sc.mapPartitions是按RDD分区进行数据统计处理. 测试一下: val data = sc.parallelize(1 to 6, ...

  3. Xamarin Anroid App访问网站失败

    Xamarin Anroid App访问网站失败 错误信息:net::ERR_NAME_NOT_RESOLVED如果电脑同时有有线网卡和无线网卡,电脑使用无线网卡上网,而有线网卡不上网.这时,就会出现 ...

  4. win 7 普通家庭版 装IIS

    每当一个程序员入职的时候,几乎都会干一件事情,就是重装操作系统,这是一场不易之战: 1)耗时太长: 2)容易遇到怪异的系统行为. 1.win7为毛装不上VS2012 先装一个win7 x64 旗舰版, ...

  5. JAVA7遍历文件夹

    在JAVA7中提供了新的遍历文件的方法,比原有File类的递归遍历效率要好大约30%左右. 测试结果: 测试用的File类的递归,是经过对比测试几种方法,找出相对效率较好的来和JAVA7进行测试. 1 ...

  6. 【BZOJ】2648: SJY摆棋子 & 2716: [Violet 3]天使玩偶(kdtree)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2716 http://www.lydsy.com/JudgeOnline/problem.php?id ...

  7. 【BZOJ】1192: [HNOI2006]鬼谷子的钱袋(水题)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1192 看到题我就好像想起以前小学升学考数学的最后一题,将一条金块分割最少的部分,使得每一天都能够支付 ...

  8. [简单]poi word2007表格按模版样式填充行数据

    主要实现了按照模版行的样式填充数据,针对的是动态数据,静态数据可以直接替换变量实现,先说下缺点:1)暂未实现特殊样式填充(如列合并(跨行合并)),只能用于普通样式(如段落间距 缩进 字体 对齐)2)数 ...

  9. Coremail邮件系统存储型XSS两个

    (1):Coremail邮件系统存储型XSS之一 给受害者发送主题如下的邮件: <svg onload='img=new Image();img.src="//x55.me/geo.p ...

  10. 将正确的 HTTP 头转发给后端服务器的一些问题

    Apache Software Foundation 的 HTTP 服务器项目(通常称为 Apache)是当今互联网上占据优势的 Web 服务器,它占据了 60% 以上的市场份额.Apache 服务器 ...