Spring总结二:IOC(控制反转)xml方式
1,简介:
IoC :Inverse of control 控制反转 ,思想就是在项目中引入一个工厂容器,对项目中接口依赖对象的创建,实现项目中对于依赖对象解耦合。
将程序中对象的创建权以及对象的整个生命周期(创建、初始化、销毁),交给工厂容器来管理,而我们不用关心怎么去创建对象(new对象),只需要关注操作对象即可。
2,Spring实例化对象的三种方式:
1,默认无参构造器创建
2,静态工厂方法创建
3,实例工厂方法创建
无参构造器创建:
applicationContext.cml配置:
<?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.xsd"> <!--无参构造器--> <bean id="bean1" class="com.zy.IoC.Bean1"></bean> </beans>
JavaBean类 Bean1:
public class Bean1 { public Bean1() { System.out.println("Bean1的无参构造方法"); } }
测试:
@Test public void createObjByConstructor() { //获取spring容器 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); //从容器中获取对象 Bean1 bean1 = ac.getBean("bean1", Bean1.class); System.out.println("******************************"); System.out.println(bean1); }
运行结果:
静态工厂方法创建:
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.xsd"> <!--无参构造器--> <bean id="bean1" class="com.zy.IoC.Bean1"></bean> <!--静态工厂方法--> <bean id="bean2" class="com.zy.IoC.Bean2Factory" factory-method="getBean2"></bean> </beans>
JavaBean类 Bean2:
public class Bean2 { public Bean2() { System.out.println("Bean2的无参构造方法"); } }
静态工厂:
public class Bean2Factory { public Bean2Factory() { System.out.println("Bean2Factory 的构造方法"); } public static Bean2 getBean2(){ return new Bean2(); } }
测试:
@Test public void createObjByStaticFactory() { //获取spring容器 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); //获取对象 Bean2 bean2 = ac.getBean("bean2", Bean2.class); System.out.println("******************************"); System.out.println(bean2); }
运行结果:
实例工厂方法创建:
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.xsd"> <!--无参构造器--> <bean id="bean1" class="com.zy.IoC.Bean1"></bean> <!--静态工厂方法--> <bean id="bean2" class="com.zy.IoC.Bean2Factory" factory-method="getBean2"></bean> <!--实例化工厂方法--> <bean id="bean3Factory" class="com.zy.IoC.Bean3Factory"></bean> <bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean> </beans>
JavaBean类 Bean3:
public class Bean3 { public Bean3() { System.out.println("Bean3的无参构造方法"); } }
工厂:
public class Bean3Factory { public Bean3Factory() { System.out.println("Bean3Factory 的构造方法"); } public Bean3 getBean3(){ return new Bean3(); } }
测试:
@Test public void createObjByFactory() { //获取spring容器 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); //获取对象 Bean3 bean3 = ac.getBean("bean3", Bean3.class); System.out.println("******************************"); System.out.println(bean3); }
运行结果:
其实除了以上三种方法以外还有一种方法就是我们自己写一个工厂类来实现FactoryBean接口:
实现FactoryBean接口:
<?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.xsd"> <!--配置bean标签,提供对象实现类型--> <!--id或者name 是对象的唯一标识 class配置对象的全路径--> <bean id="userDao" class="com.zy.dao.impl.UserDaoImpl2"></bean> <bean id="userService" lazy-init="true" class="com.zy.service.impl.UserServiceImpl"> <property name="userDao" ref="userDao"></property> </bean> <!--无参构造器--> <bean id="bean1" class="com.zy.IoC.Bean1" lazy-init="true"></bean> <!--静态工厂方法--> <bean id="bean2" class="com.zy.IoC.Bean2Factory" factory-method="getBean2"></bean> <!--实例化工厂方法--> <bean id="bean3Factory" class="com.zy.IoC.Bean3Factory"></bean> <bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean> <!--自己创建工厂(实现FactoryBean接口)--> <bean id="bean3_2" class="com.zy.IoC.MyFactoryBean"></bean> </beans>
自己创建的工厂:
public class MyFactoryBean implements FactoryBean { @Override public Object getObject() throws Exception { //这里返回实例 return new Bean3(); } @Override public Class<?> getObjectType() { return null; } @Override public boolean isSingleton() { return false; } }
测试及运行结果大家可以自己实现以下,这里就不多做讲述了。
可以看出以上方法都可以把对象创建出来,但是会有一个问题 不知道大家有没有发现,就是每次获取spring容器的时候,都会创建一个新的spring容器,而且这个容器在被创建的时候会把所有写在配置文件中的对象都创建出来,你用的时候 再根据需要把对应的对象给你,那么这种方式是不可取的,那么现在给大家介绍一下lazy-init来解决这个问题,其实还有更好的解决方案,这个我们以后的文章里再说。
3,配置中的一些其他属性:
lazy-init:(懒加载,容器创建对象的时机配置)
现在我们把我们的applicationContext.xml文件的配置写成这样的(无参构造器的bean配置里把lazy-init=“true”):
<?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.xsd"> <!--无参构造器--> <bean id="bean1" class="com.zy.IoC.Bean1" lazy-init="true"></bean> <!--静态工厂方法--> <bean id="bean2" class="com.zy.IoC.Bean2Factory" factory-method="getBean2"></bean> <!--实例化工厂方法--> <bean id="bean3Factory" class="com.zy.IoC.Bean3Factory"></bean> <bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean> </beans>
运行测试实例化工厂方法的test方法得出如下结果:
会发现Bean1的无参构造方法没有被调用,也就是说我们使用了lazy-init懒加载以后,Bean1的构造在不被调用的时候 是不会加载的。
Scope:(Bean的作用域配置)
既然说过了lazy-init是懒加载,那就有必要再说一下设置Bean的作用域的scope,scope的值有以下几种,默认为第一个singleton:
重点为singleton和prototype:
-
-
prototype 原型 多实例 (每次getBean都会返回 一个新的实例 )
实例如下:
// 单例 public class SingletonBean { public SingletonBean() { System.out.println("单实例Bean SingletonBean 初始化..."); } } // 多实例 public class PrototypeBean { public PrototypeBean() { System.out.println("多实例bean PrototypeBean 初始化 ..."); } }
配置:
<!-- ========================================= c_scope bean的作用域 --> <!-- 如果不指定scope属性,默认就是单实例 --> <bean id="singletonBean" class="com.zy.spring.SingletonBean" /> <bean id="prototypeBean" class="com.zy.spring.PrototypeBean" scope="prototype"/>
测试:
@Test public void testScope() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext( "applicationContext.xml"); // 单例 SingletonBean singletonBean1 = (SingletonBean) applicationContext .getBean("singletonBean"); SingletonBean singletonBean2 = (SingletonBean) applicationContext .getBean("singletonBean"); System.out.println(singletonBean1); System.out.println(singletonBean2); // 多例 PrototypeBean prototypeBean1 = (PrototypeBean) applicationContext .getBean("prototypeBean"); PrototypeBean prototypeBean2 = (PrototypeBean) applicationContext .getBean("prototypeBean"); System.out.println(prototypeBean1); System.out.println(prototypeBean2); }
运行结果,很明显单实例的只被初始化了一次,后面每次拿到的都是引用,多实例是每次都初始化一次:
4,Spring容器的生命周期
JavaBean类:
public class SpringLifeCycle { //构造方法 public SpringLifeCycle() { System.out.println("SpringLifeCycle 构造..."); } //初始化方法 public void init() { System.out.println("SpringLifeCycle 初始化..."); } //销毁方法 public void destroy() { System.out.println("SpringLifeCycle 销毁..."); } public void helloSpring() { System.out.println("hello spring !"); } }
Bean的初始化,销毁属性配置:(init-method初始化方法,destroy-method销毁方法)
<bean id="springLifecycle" class="com.zy.spring.SpringLifeCycle" init-method="init" destroy-method="destroy" />
测试:
@Test public void testScope() { ApplicationContext ac = new ClassPathXmlApplicationContext( "applicationContext.xml"); SpringLifeCycle springLifeCycle = (SpringLifeCycle) ac.getBean("springLifeCycle"); springLifeCycle.helloSpring(); // 调用close(ApplicationContext没有close方法,需要转子类调用close) ClassPathXmlApplicationContext classAc = (ClassPathXmlApplicationContext) ac; classAc.close(); }
运行结果: