Spring回顾(一)IoC & DI
来源:互联网 发布:淘宝下架宝贝在哪里 编辑:程序博客网 时间:2024/05/16 12:35
什么是IoC?何为DI?
IoC是Sprnig框架实现的一种代替程序员,管理Java类的模式。IoC全称为Inversion of Control,即控制反转。在Spring项目中,将Java类的控制权交给了Spring的IoC容器。类与类之间的泛化关系、依赖关系都能通过Spring的配置来实现,而不需要手动编写。
DI,全称为Dependency Injection,即依赖注入。在Spring通过配置文件配置了依赖关系之后,可以通过多种方式对对象进行注入,比如说Service实现类中的方法需要依赖dao实现类,我们就能通过Spring配置文件写好注入配置,在使用时,我们只需要定义好dao接口,而不需要去获取它的实例,由Spring为我们注入。
能通过Spring的IoC容器和DI做什么?
1. IoC(控制反转)
控制反转,能让spring容器为我们创建对象。简单来说,我们只需要准备好Object object
Spring能帮我们实现余下的new Object()
部分。在Spring中,每个被放入容器的类被成为bean,ApplicationContext代表了IoC容器,我们可以通过这个类来读取配置文件,根据配置文件实例化bean。下面看看如何通过配置实现控制反转
1.1 配置文件
配置文件一般放在class目录下,即开发中的src目录。配置文件的主要结构如下:
<?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"> <!-- beans 存放了很多个类 把一个类放入到spring容器中,该类就是bean --> <!-- 一个bean就是描述一个类 id就是标示符 命名规范:类的第一个字母变成小写,其他的字母保持不变 class为类的全名 --> <bean id="helloWorld" class="com.spring.ioc.HelloWorld"></bean></beans>
1.2 ApplicationContext 的使用
ApplicationContext在Spring中代表一个IoC容器,ApplicationContext只是一个接口,在这里我用ClassPathXmlApplicationContext这个实现类来直接获取配置文件。其中在容器中对象的创建又有三种方法:根据默认构造方法创建、静态工厂方法创建、实例工厂方法创建
①默认构造方法创建
springIoc容器默认情况下会根据bean的构造函数来实例化对象。所以在bean的配置中我们可以添加参数,参数可以是变量也可以是另一个bean的引用,如果是bean的引用,则使用ref=”bean_id”来关联。
配置方式applicationContext.xml
<bean id="helloWorld" class="com.spring.ioc.HelloWorld"></bean>
HelloWorld.java
package com.spring.ioc;public class HelloWorld { public HelloWorld(){ System.out.println("create a HelloWorld!"); } public void hello(String name){ System.out.println("Hello," + name); }}
IoCTest.java
package com.spring.ioc;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class IoCTest { @Test public void testIoC(){ //读取配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //通过getBean方法得到 HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld"); helloWorld.hello("Cindy"); }}
②静态工厂方法创建对象
可以在配置bean的时候可以配置使用静态工厂来实例化对象。Spring容器会在内部调用静态工厂的实例化方法来实例化对象。
配置方式:applicationContext.xml
<bean id="helloWorld" class="com.spring.ioc.HelloWorldFactory" factory-method="getInstance"> </bean>
静态工厂HelloWorldFactory.java
package com.spring.ioc;public class HelloWorldFactory { public static HelloWorld getInstance(){ return new HelloWorld(); }}
③实例工厂创建对象
使用实例工厂方法实例化对象,在定义bean的时候使用factory-bean属性和factory-method属性,来指定实例工厂的实例方法。与静态工厂方法不同,这里是先实例化了一个工厂类,然后调用了实例化工厂方法,而静态工厂方法不实例化工厂类,直接调用其静态实例化方法。
配置方式:applicationContext.xml
<bean id="helloWorldFactory" class="com.spring.ioc.HelloWorldFactory2"></bean><bean id="helloWorld" factory-method="getInstance" factory-bean="helloWorldFactory"></bean>
实例工厂HelloWorldFactory2.java
package com.spring.ioc;public class HelloWorldFactory2 { public HelloWorldFactory2(){ System.out.println("create a HelloWorldFactory"); } public HelloWorld getInstance(){ return new HelloWorld(); }}
1.3 什么时候实例化对象?
①加载Spring容器,加载过程中,调用bean的构造函数为bean创建对象。
②将bean的lazy-init属性,设置为true(默认为false),设置延迟加载,spring容器加载时不实例化,在getBean()的时候才实例化。
一般情况下使用第一种方式,因为在启动过程中就能检测出spring配置文件中包含的错误,更加安全。第二种在启动过程中发现不了配置文件错误。如果要加载的bean实在太消耗性能,再考虑使用第二种方法。
1.4 bean的单例模式和多例模式
在配置bean的过程中,可以为其指定是否使用单例模式实例化对象,默认为单例模式,即只实例化一次,多次使用。设置的方法为:
① 多例模式:scope=prototype
<bean id="helloWorld" class="com.spring.ioc.HelloWorld" scope="prototype"></bean>
②单例模式(defalut): scope=singleton
<bean id="helloWorld" class="com.spring.ioc.HelloWorld" scope="singleton"></bean>
1.5 bean的init方法,destory方法
在配置bean的时候,可以为其指定init()方法和destory()方法,分别在实例化和销毁的时候执行。其中在容器关闭时,bean销毁。
配置了之后整个流程可表示为:构造方法(创建对象)->init方法->其他方法->destory方法
*当scope=prototype的时候,spring容器不会执行destory方法
配制方法 applicationContext.xml :
<bean id="helloWorld" class="com.spring.ioc.HelloWorld" init-method="init" destroy-method="destroy"></bean>
HelloWorld.java
package com.spring.ioc;public class HelloWorld { public HelloWorld(){ System.out.println("create a HelloWorld!"); } public void hello(String name){ System.out.println("Hello," + name); } public void init(){ System.out.println("init HelloWorld"); } public void destroy(){ System.out.println("destroy HelloWorld"); }}
1.6 bean继承关系
在spring容器中使用parent属性指定父类,实现继承。例子:
package com.spring.xml.extend;public class Animal { public void walk(){ System.out.println("Animal walking"); }}
package com.spring.xml.extend;public class Dog extends Animal {}
配置:
<bean class="com.spring.xml.extend.Animal" id="animal"></bean><bean class="com.spring.xml.extend.Dog" id="dog" parent="animal"></bean>
2. DI(依赖注入)
2.1 setter方式注入
配置bean的时候,我们可以在配置文件中指定实例化时,要注入的属性值。这些值可以是基本数据类型、引用类型、集合类型、或者Propertie,只要在bean的类定义中提供setter方法就能通过配置注入,配置的方法如下:
applicationContext.xml
<bean id="person" class="com.spring.di.Person"> <!-- property描述的就是bean中的属性 name属性就是描述属性的名称 value就是值 如果是基本属性(String),就用value赋值 ref 如果是引用类型,用ref赋值 --> <property name="pid" value="1"></property> <property name="name" value="Cindy"></property> <!-- 注入bean --> <property name="student" ref="student"></property> <property name="lists"> <list> <value>list1</value> <value>list2</value> <!-- list中存放一个student对象 --> <ref bean="student"/> </list> </property> <property name="objects"> <list> <value>obj1</value> <ref bean="student"/> </list> </property> <property name="sets"> <set> <value>set1</value> <ref bean="student"/> </set> </property> <property name="map"> <map> <entry key="m1"> <value>m1</value> </entry> <entry key="m2"> <ref bean="student"/> </entry> </map> </property> <property name="properties"> <props> <prop key="p1">p1</prop> <prop key="p2">p2</prop> </props> </property></bean><bean id="student" class="com.spring.di.Student" scope="prototype"></bean>
Student.java
package com.spring.di;public class Student { public Student(){ System.out.println("student"); } public void say(){ System.out.println("student"); }}
Person.java
public class Person { private Long pid; private String name; private Student student; private List lists; private Set sets; private Map map; private Object[] objects; private Properties properties; public Person(){ System.out.println("person"); } //... //省略setter方法}
2.2 Constructor 注入
除了调用setter方法注入,还能通过类的构造器来注入参数,同样是从配置文件中对bean进行配置。首先在类中定义好构造器方法,然后在配置文件中设置参数。
配置方法:
applicationContext.xml
<bean id="person1" class="com.spring.di.Person1"> <constructor-arg value="Cindy" index="0"></constructor-arg> <constructor-arg ref="student" index="1"></constructor-arg></bean>
Person1.java
package com.spring.di;public class Person1 { private String name; private Student student; public Person1(String name, Student student) { this.name = name; this.student = student; }}
IoC 和 DI 带来的好处(优势)
让客户端实现完全面向接口编程,在编写客户端的时候,不用关心实现类为什么具体类型,只用接口类型来完成工作,接口需要具体为何种类型的实例,由配置文件决定。举个例子,在一个struts2的aciton中,用接口定义了一个service,而这个service通过spring注入,那么开发action的人员就不需要管service具体是如何实现的,把编写service的工作分离出去,方便团队开发,避免编写过程中的冲突。
Spring是如何实现IoC和DI的
了解Spring框架底层是如何实现控制反转和依赖注入,需要深入研究源码。因为我还没有深入研究过,只知道大概是使用了Java的反射机制,来操作类。有待自己深入研究。
- Spring回顾(一)IoC & DI
- Spring回顾(二)注解实现IoC和DI
- Spring之IOC/DI(一)
- Spring学习笔记(一)----IoC之DI
- Spring学习笔记(一)----IoC之DI
- Spring(四):IOC,DI
- Spring(1)IOC/DI
- Spring基础(IOC&DI)
- Spring教程系列(一)-IoC与DI
- Spring应用(一) IOC和DI总结
- Spring IOC 学习笔记(一) IoC和DI概述
- Spring IOC 学习笔记(一) IoC和DI概述
- spring 学习笔记(2)--IOC(DI)
- Spring(二):IOC和DI
- spring入门案例(IoC和DI)
- spring mvc 扫描注解(ioc,di)
- Spring核心知识(IOC/DI、AOP)
- Spring模拟(DI,IOC)
- 实现一个简单的HttpClient连接池(转自博客园)
- HDU1166:敌兵布阵(CDQ分治)
- 线性模型学习笔记
- 移动端前端页面实现学习笔记
- ArcGIS属性表操作
- Spring回顾(一)IoC & DI
- 利用插件扩展Qt本身
- Java JVM——基础概念介绍
- Robot Framework + Appium测试Android设备
- c++ 构造没完成 别的对象不能访问 析构时基类不要调用虚函数
- logstash 条件判断语句
- 温故而知新(五)java基础:String、StringBuffer 、StringBuilder
- 代码结构中Dao,Service,Controller,Util,Model是什么意思,为什么划分?
- ES-Hadoop学习之ES和HDFS数据交换