问题?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. 【练习】ViewPager标签滑动

    效果图: 布局: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:a ...

  2. aac格式解析

    AAC格式有以下两种: ADIF:Audio Data Interchange Format 音频数据交换格式.这种格式的特征是可以确定的找到这个音频数据的开始,不需进行在音频数据流中间开始的解码,即 ...

  3. DOM--1 遵循最佳实践

    为重用命名空间而进行规划 (function() { function $(id) { return document.getElementById(id); } function alertNode ...

  4. 直接操作游戏对象C#游戏开发

    直接操作游戏对象C#游戏开发 2.2.3  直接操作游戏对象 在Inspector视图里通过设置属性而改变游戏场景中游戏对象的状态,太过抽象,毕竟数字并不够直观.其实,改变游戏对象的状态,完全有最最直 ...

  5. Zookeeper实战之单机模式

    Zookeeper介绍 Zookeeper 分布式服务框架是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务.状态同步服务.集群管理.分布式应用配置项的管理等.本文主要从使用者角度来介 ...

  6. HDU1667 : The Rotation Game

    考虑枚举最后中间的数字,然后可以用一个24位的整数来表示一个状态,一共有C(24,8)=735471种状态,然后BFS即可. 比赛的时候由于手速问题没写完TAT 写完后在坑爹评测机上还是TLE. 所以 ...

  7. HDU 1429 (BFS+记忆化状压搜索)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1429 题目大意:最短时间内出迷宫,可以走回头路,迷宫内有不同的门,对应不同的钥匙. 解题思路: 要是 ...

  8. IOS 项目 小说 1

    架构: logo: logo标识(在image文件夹中修改某图片名称为icon) default: 默认页面的启动效果(在image文件夹中修改某图片名称为Default) image:存放图片(根目 ...

  9. BestCoder Round #72

    由于第一次打,只能在div2打.(这么好的机会还没AK真是丢人) T1 Clarke and chemistry 枚举题不解释(我不会告诉你我上来WA了四发的) T2 Clarke and point ...

  10. 面试题中遇到的SQL题目

    1.假设有一张表示cj表 Name Subject Result 张三 语文 80 张三 数学 90 张三 物理 85 李四 语文 85 李四 数学 92 李四 物理 82 要求查询结果: 姓名 语文 ...