(1)IOC概念
Inversion of Control 控制反转。控制反转:控制权的转,即把创建对象的权利,反转给第三方spring框架去创建(new)
(2)IOC简单演示
1、创建hello类
package com.suning.Spring.IOC;
public class hello {
public hello(){
System.out.println("hello_create");
}
public void sayHello() {
System.out.println("hello spring");
}
public void init() {
System.out.println("Hello.init...");
}
public void destroy() {
System.out.println("Hello.destroy...");
}
}
helloTest
package com.suning.Spring.IOC;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;
public class helloTest {
@Test
public void test1(){
ApplicationContext hello = new ClassPathXmlApplicationContext("applicationContext.xml");
hello he = hello.getBean("hello", hello.class);
he.sayHello();
}
}
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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!--
<bean spring框架读取到bean的时候,就知道需要创建一个对象
id: 创建完的对象名称,此名称必须唯一
class: 全路径类名(包名+类名),指定spring要实例化哪一个类的对象
底层:Object obj =
Class.forName("com.hdu.ioc.Hello").newInstance();
对象实例化完毕后把id的值作为key,把实例化完的对象作为value
存储到map集合中,以便需要时根据key来去除value
全路径类名是否正确:ctrl+鼠标
-->
<bean id="hello" class="com.suning.Spring.IOC.hello"></bean>
</beans>
2、Spring原理:
①启动spring容器,并读取和解析清单文件
②把spring.xml中的bean节点的内容解析出并存储(map)
③ 循环遍历map集合中的所有数据,取出class属性对应的值,反射实例化对象
Objectobj=Class.forName(“包名.类名”).newInstance();
④把所有创建完的对象存储另一个map集合,id当key,对象当value
3、getBean几种方式
//根据id,从spring容器中获取对象
//Hello hello = (Hello)context.getBean(“hello”);
//根据类型,从spring容器找那个获取对象,类型的对象必须唯一
//Hello hello = context.getBean(Hello.class);
//根据id和类型来取对象
Hello hello = context.getBean(“hello”, Hello.class);
(3)spring容器实例化对象的四种方式
1、通过无参构造的方式实例化对象(类中必须存在无参构造)
public class Hello {
public Hello() {
System.out.println("Hello.created");
}
public void sayHello() {
System.out.println("hello spring");
}
}
<!-- 默认构造
-->
<bean id="hello"
class="com.hdu.ioc.Hello">
</bean>
@Test
public void testMethod() {
//启动spring的容器,spring读取spring.xml文件
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"resources/spring_factory.xml"});
//从spring容器中取出spring创建完的对象
//根据id和类型来取对象
Hello hello = context.getBean("hello", Hello.class);
hello.sayHello();
}
2、静态工厂
有些类不能直接实例化,就不能直接通过new关键字来创建,类似这样的对象我们要通过静态工厂模式来创建对象。没有静态方法就无法直接调用。
<!--
静态工厂 因为getInstance这个方法是静态方法,Calendar是抽象类,不能无参构造
-->
<bean id="cal"
class="java.util.Calendar"
factory-method="getInstance" >
</bean>
public class TestIOC {
@Test
public void testMethod1() {
Calendar cal = Calendar.getInstance();
System.out.println(cal.getTime());
}
3、实例工厂
静态工厂设计模式不会创建类对象,直接调用静态方法。而工厂方法设计模式会创建类,然后通过xml中配置去访问其方法。
<!-- 实例工厂 可以由程序员自己控制调用指定的方法获取对象
但对象还不是spring创建,在别的渠道创建完交给spring容器管理
-->
<bean id="if" class="com.hdu.factory.InstanceFactory"></bean>
<bean id = "cal1"
factory-bean="if"
factory-method="getCalendar" >
</bean>
public class InstanceFactory {
public Calendar getCalendar() {
return Calendar.getInstance();
}
public class TestIOC {
@Test
public void testMethod2() {
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"resources/spring_factory.xml"});
Calendar cal = context.getBean("cal1",Calendar.class);
System.out.println(cal.getTime());
}
4、Spring工厂
这是spring框架自身提供的,它需要实现FactoryBean接口,实现代码就必须写在getObject()方法中。spring工厂的优点在于,只要实现一个接口即可,简单方便。
<!-- spring工厂 -->
<bean id="hello" class="com.hdu.factory.SpringFactory"></bean>
public class SpringFactory implements FactoryBean<Hello>{
@Override
public Hello getObject() throws Exception {
return new Hello();
}
@Override
public Class<?> getObjectType() {
return Hello.class;
}
@Override
public boolean isSingleton() {
return false;
}
public class TestIOC {
@Test
public void testMethod3() {
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"resources/spring_factory.xml"});
Hello hello = context.getBean("hello",Hello.class);
hello.sayHello();
}
(4)Spring对象
1、单例
当 scope=“singleton” 时,结果为 true。不写scope属性时,结果仍为true,证明默认对象是以单例创建的。
<!--
scope:范围,如果bean节点中使用的scope属性,就是要指定当前对象的范围
scope="singleton" 单例,默认,不写也是单例
scope="prototype" 多例,什么时候用,什么时候实例化对象
-->
<bean id="hello"
class="com.hdu.ioc.Hello"
scope="singleton">
</bean>
public class TestIOC {
/**
* 测试单例和多例
*/
@Test
public void testMethod() {
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"resources/spring.xml"});
Hello hello = context.getBean("hello",Hello.class);
Hello hello2 = context.getBean("hello",Hello.class);
System.out.println(hello == hello2);
}
2、多例
当 scope=“prototype” 时,以上测试,结果为false。
<!--
scope:范围,如果bean节点中使用的scope属性,就是要指定当前对象的范围
scope="singleton" 单例,默认,不写也是单例
scope="prototype" 多例,什么时候用,什么时候实例化对象
-->
<bean id="hello"
class="com.hdu.ioc.Hello"
scope="prototype">
</bean>
3、懒加载
多例对象都是懒加载
<!--
lazy-init="true" ,什么时候用,什么时候实例化
-->
<bean id="hello"
class="com.hdu.ioc.Hello"
scope="singleton"
lazy-init="true">
</bean>
(5)初始化和销毁方法
Hello
public class Hello {
public Hello() {
System.out.println("Hello.created");
}
public void sayHello() {
System.out.println("hello spring");
}
public void init() {
System.out.println("Hello.init...");
}
public void destroy() {
System.out.println("Hello.destroy...");
}
applicationContext
<bean id="hello"
class="com.hdu.ioc.Hello"
scope="singleton"
init-method="init"
destroy-method="destroy"
lazy-init="true">
</bean>
TestIOC
public class TestIOC {
@Test
public void testMethod() {
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"resources/spring.xml"});
Hello hello = context.getBean("hello",Hello.class);
((AbstractApplicationContext) context).close();
}