spring ioc和di
来源:互联网 发布:linux ssr 客户端 编辑:程序博客网 时间:2024/05/20 23:07
很多人认为IOC就是DI他们之间是对等的,其实不然。
很多文章中都提到他们的分别依赖:
谁依赖于谁?为什么需要依赖?
注入:谁注入于谁?到底注入什么?
控制反转:谁控制谁?控制什么?
这种描述很难让别人理解,感觉有点教科书的意味。下面我就简单的说下我的看法:
一、IOC和DI区别
IOC( inversion of control)控制反转,控制反转是一种思想,结合程序通俗的讲,创建对象的方式反转了。
以前对象的创建是由我们开发人员自己维护创建,包括依赖关系都是自己进行注入(创建依赖对象new),例如:我们经常提到的三层框架Web层、Service层、Dao层。web层依赖于service层,service依赖于dao层,以前我们管理service层调用dao层的数据时,都会new一个对象调用其中的方法。
使用spring后对象的创建及依赖的对象都由spring完成创建和注入,控制反转就是对象的创建方式,从我们自己创建到交个spring(程序)进行创建管理
DI(Dependency Injection)依赖注入,依赖注入是一种技术,它是对控制反转这种思想进行技术支撑。依赖注入即控制反转中举的例子。
二、Spring创建Bean对象的三种方式
首先我们看看不用spring时如何创建对象
public class UserServiceImpl {public List<User> getUserList(){//servi层调用dao层的方法,需要手动创建dao对象UserDao userDao = new UserDao();return userDao.getUserList();}}使用spring,spring就会自动创建对象(前提按照一定的规则,这个规则是spring规定的)
第一种方式构造器注入创建(默认的创建方式)
public class User {public User() {System.out.println("User对象构造器注入创建!!!!");}private String name;private Integer age;public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + "]";}}Spring配置文件applicationContext.xml中配置
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "> <!-- set方式注入: --> <bean name="user" class="cn.mingxungu.bean.User" /></beans>
测试代码
@Testpublic void fun1(){//1 创建容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("cn/mingxungu/c_injection/applicationContext.xml");//2 向容器"要"user对象User u = (User) ac.getBean("user");//3 打印user对象System.out.println(u);}结果:
User对象构造器注入创建!!!!
User [name=null, age=null]
第二种方式静态工厂创建(了解)
public class UserFactory {public static User createUser(){System.out.println("静态工厂创建User");return new User();}}Spring配置文件applicationContext.xml中配置
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "><!-- 创建方式2:静态工厂创建 调用UserFactory的createUser方法创建名为user2的对象.放入容器 --><bean name="user2" class="cn.mingxungu.b_create.UserFactory" factory-method="createUser" ></bean></beans>
测试代码
//创建方式2:静态工厂@Testpublic void fun2(){//1 创建容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("cn/mingxungu/b_create/applicationContext.xml");//2 向容器"要"user对象User u = (User) ac.getBean("user2");//3 打印user对象System.out.println(u);}输出结果
静态工厂创建User
User [name=null, age=null]
注意:静态工厂方法在配置文件中制定了工厂方法名称factory-method="createUser"
第三种方式实例工厂创建(了解)
public class UserFactory {public User createUser2(){System.out.println("实例工厂创建User");return new User();}}Spring配置文件applicationContext.xml中配置
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "><!-- 创建方式3:实例工厂创建 调用UserFactory对象的createUser2方法创建名为user3的对象.放入容器 --><bean name="user3" factory-bean="userFactory"factory-method="createUser2" ></bean><bean name="userFactory" class="cn.mingxungu.b_create.UserFactory" ></bean></beans>测试代码
//创建方式3:实例工厂@Testpublic void fun3(){//1 创建容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("cn/mingxungu/b_create/applicationContext.xml");//2 向容器"要"user对象User u = (User) ac.getBean("user3");//3 打印user对象System.out.println(u);}
输出结果
实例工厂创建User
User [name=null, age=null]
总结:
一、<bean>元素指定了factory-method属性,Spring就不再调用构造器来创建Bean实例,而是调用工厂方法来创建Bean实例。如果同时指定了class和factory-method两个属性,Spring就会调用静态工厂方法来创建Bean。Spring将先解析配置文件,并根据配置文件指定的信息,通过反射调用静态工厂类的静态工厂方法,将该静态工厂方法的返回值作为Bean实例。在这个过程中,Spring不再负责创建Bean实例,Bean实例是由用户提供的静态工厂类负责创建的。
二、实例工厂方法与静态工厂方法只有一点不同:调用静态工厂方法只需要使用工厂类即可,而调用实例工厂方法则需要工厂实例。所以在配置时,静态工厂方法使用class指定静态工厂类,实例工厂方法使用factory-bean指定工厂实例。
采用实例工厂方法创建Bean的<bean>元素时需要指定两个属性:
factory-bean:工厂bean的id
factory-method:实例工厂的工厂方法
三、Bean 生命周期
详解:
Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:
1、Bean自身的方法:这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法
2、Bean级生命周期接口方法:这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法
3、容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
4、工厂后处理器接口方法:这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器 接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。说明:
在配置文件aplicationContext.xml中配置的bean的生命周期
<bean name="user" class="cn.mingxungu.bean.User" init-method="init" destroy-method="destory" />
init-method="init":配置一个方法作为生命周期初始化方法,在该Bean中编写一个init方法。spring会在对象创建之后立即调用.
destroy-method="destory":配置一个方法作为生命周期的销毁方法,在该Bean中编写一个destory方法。spring容器在关闭并销毁所有容器中该对象之前调用.
详细的测试参考:http://www.cnblogs.com/zrtqsk/p/3735273.html
四、Bean属性的注入
注入方式:set方法注入、构造函数注入、p名称空间注入、spel注入
set方法注入:
<!-- set方式注入: --><bean name="user" class="cn.mingxungu.bean.User" ><!--值类型注入: 为User对象中名为name的属性注入tom作为值 --><property name="name" value="tom" ></property><property name="age" value="18" ></property><!-- 引用类型注入: 为car属性注入下方配置的car对象 --><property name="car" ref="car" ></property></bean> <!-- 将car对象配置到容器中 --> <bean name="car" class="cn.mingxungu.bean.Car" > <property name="name" value="兰博基尼" ></property> <property name="color" value="黄色" ></property> </bean>构造函数注入(掌握)
<!-- 构造函数注入 --><bean name="user2" class="cn.mingxungu.bean.User" ><!-- name属性: 构造函数的参数名 --><!-- index属性: 构造函数的参数索引 --><!-- type属性: 构造函数的参数类型--><constructor-arg name="name" index="0" type="java.lang.Integer" value="999" ></constructor-arg><constructor-arg name="car" ref="car" index="1" ></constructor-arg></bean><!-- 将car对象配置到容器中 --><bean name="car" class="cn.mingxungu.bean.Car" > <property name="name" value="兰博基尼" ></property> <property name="color" value="黄色" ></property></bean>
p名称空间注入
<!-- p名称空间注入, 走set方法1.导入P名称空间 xmlns:p="http://www.springframework.org/schema/p"2.使用p:属性完成注入|-值类型: p:属性名="值"|-对象类型: p:属性名-ref="bean名称" --><bean name="user3" class="cn.mingxungu.bean.User" p:name="jack" p:age="20" p:car-ref="car" /><!-- 将car对象配置到容器中 --><bean name="car" class="cn.mingxungu.bean.Car" > <property name="name" value="兰博基尼" ></property> <property name="color" value="黄色" ></property></bean>
spel注入
<!-- spel注入: spring Expression Language sping表达式语言 --><bean name="user4" class="cn.mingxungu.bean.User" ><property name="name" value="#{user.name}" ></property><property name="age" value="#{user3.age}" ></property><property name="car" ref="car" ></property></bean><!-- 将car对象配置到容器中 --><bean name="car" class="cn.itcast.bean.Car" > <property name="name" value="兰博基尼" ></property> <property name="color" value="黄色" ></property></bean>
复杂类型的注入
实体:
public class CollectionBean {private Object[] arr;//数组类型注入private List list;//list/set 类型注入private Map map;//map类型注入private Properties prop;//properties类型注入public Object[] getArr() {return arr;}public void setArr(Object[] arr) {this.arr = arr;}public List getList() {return list;}public void setList(List list) {this.list = list;}public Map getMap() {return map;}public void setMap(Map map) {this.map = map;}public Properties getProp() {return prop;}public void setProp(Properties prop) {this.prop = prop;}@Overridepublic String toString() {return "CollectionBean [arr=" + Arrays.toString(arr) + ", list=" + list + ", map=" + map + ", prop=" + prop+ "]";}}
配置文件
<bean name="cb" class="cn.mingxungu.c_injection.CollectionBean" ><!-- 如果数组中只准备注入一个值(对象),直接使用value|ref即可 <property name="arr" value="tom" ></property>--><!-- array注入,多个元素注入 --><property name="arr"><array><value>tom</value><value>jerry</value><ref bean="user4" /></array></property><!-- 如果List中只准备注入一个值(对象),直接使用value|ref即可 <property name="list" value="jack" ></property>--><property name="list" ><list><value>jack</value><value>rose</value><ref bean="user3" /></list></property><!-- map类型注入 --><property name="map" ><map><entry key="url" value="jdbc:mysql:///crm" ></entry><entry key="user" value-ref="user4" ></entry><entry key-ref="user3" value-ref="user2" ></entry></map> </property><!-- prperties 类型注入 --><property name="prop" ><props><prop key="driverClass">com.jdbc.mysql.Driver</prop><prop key="userName">root</prop><prop key="password">1234</prop></props></property></bean>五、Bean属性scope
scope类型:
singleton(默认值):单例对象.被标识为单例的对象在spring容器中只会存在一个实例
prototype:多例原型.被标识为多例的对象,每次再获得才会创建.每次创建都是新的对象.整合struts2时,ActionBean必须配置为多例的.
request:web环境下.对象与request生命周期一致.
session:web环境下,对象与session生命周期一致.
说明:前两个重点掌握,其他两个一般用不到
singleton测试
aplicationContext.xml配置文件
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "><!-- 创建方式1:空参构造创建 --><bean name="user" class="cn.mingxungu.bean.User" scope="singleton"/></beans>
测试
@Test//scope:singleton 单例//scope:prototype 多例public void fun4(){//1 创建容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("cn/mingxungu/b_create/applicationContext.xml");//2 向容器"要"user对象User u = (User) ac.getBean("user");User u2 = (User) ac.getBean("user");System.out.println("比较是否是一个对象"+(u==u2)); //单例:true 多例:false}
结果
User对象构造器注入创建!!!!
比较是否是一个对象true
prototype测试
只用修改上面的配置文件即可
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "><!-- 创建方式1:空参构造创建 --><bean name="user" class="cn.mingxungu.bean.User" scope="prototype"/></beans>
结果
User对象构造器注入创建!!!!
User对象构造器注入创建!!!!
比较是否是一个对象false
结论:注意到 “User对象构造器注入创建!!!!” 打印的次数不一样,并且结果也不一样,说明prototype确实是重新new了一遍
- Spring--IoC和DI
- spring--IoC和DI
- spring IOC和DI
- Spring IOC和DI
- spring IOC 和DI
- Spring IOC和DI
- Spring IoC和DI
- Spring--IOC和DI
- 【Spring】IOC和DI
- spring ioc和di
- spring IOC和DI
- Spring IOC和DI
- spring IOC 和 DI
- spring -IOC和DI
- Spring的DI和IoC
- Spring IOC和DI笔记
- Spring的IOC和DI
- Spring的IOC和DI
- VALSE 2017 | 人脸检测与识别技术年度进展概述
- 移动端开发
- AsycnTask
- mysql join 内连接和外连接
- ArrayBlockingQueue浅析
- spring ioc和di
- Quartz.net 之一 初识
- Python进行web开发--django
- linux下svn服务搭建
- 排序算法总结
- IOS推送
- cocos2d-x3.6两层Layer触摸事件传递
- config中数据库连接connectionString用机器名网站数据无法访问
- 【Centos7笔记四】vim编辑器的配置和使用