您的位置:首页 > 编程语言 > Java开发

Spring学习3—控制反转(IOC)Spring依赖注入(DI)和控制反转(IOC)

2016-02-04 17:27 876 查看
一、思想理解

Spring
能有效地组织J2EE应用各层的对象。不管是控制层的Action对象,还是业务层的Service对象,还是持久层的DAO对象,都可在Spring的
管理下有机地协调、运行。Spring将各层的对象以松耦合的方式组织在一起,Action对象无须关心Service对象的具体实现,Service对
象无须关心持久层对象的具体实现,各层对象的调用完全面向接口。当系统需要重构时,代码的改写量将大大减少。

上面所说的一切都得宜于Spring的核心机制,依赖注入。依赖注入让bean与bean之间以配置文件组织在一起,而不是以硬编码的方式耦合在一起。

依赖注入(Dependency Injection)和控制反转(Inversion of
Control)是同一个概念。具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在
传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者
实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入。

简而言之:所谓控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的。这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转;所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中。


不管是依赖注入,还是控制反转,都说明Spring采用动态、灵活的方式来管理各种对象。对象与对象之间的具体实现互相透明。

关于IOC的学习可以参看帮助文档:spring-3.2.0.M2\docs\reference\html目录下index.html的相关章节

二、IOC的相关操作

A、IOC之Bean的实例化方式(只是实例化,并没有初始化)

1)使用类无参构造器实例化

<bean id="orderService"
class="cn.itcast.OrderServiceBean"/>

2)使用静态工厂方法实例化

<bean id="personService"
class="cn.itcast.service.OrderFactory"
factory-method="createOrder"/>

public class OrderFactory {

public
static OrderServiceBean createOrder(){

return new
OrderServiceBean();

}

3)通过非静态工厂方法实例化:

<bean id="personServiceFactory"
class="cn.itcast.service.OrderFactory"/>

<bean id="personService"
factory-bean="personServiceFactory"
factory-method="createOrder"/>

public class OrderFactory {

public
OrderServiceBean createOrder(){

return new
OrderServiceBean();

}

}

-------------------------------------------------------------

B、IOC之Bean属性的依赖注入(DI)方式
(即Bean的初始化)


1)setter方法注入

Course类中存在如下setter方法:

public void setId(Intenger
id)

{ this.id = id;}

<bean
id="course" class="com.etc.vo.Course">

<property name="id">

<value>1</value>

</property>


</bean>

2)构造方法注入

public Course (Interge id ,
String title,Double price)

{this.id = id; this.title =
title; this.price = price;}

<bean
id="course4" class="com.etc.vo.Course">

<constructor-arg index="0">

<value>4</value>

</constructor-arg>

<constructor-arg index="1">

<value>Java</value>

</constructor-arg>

<constructor-arg index="2">

<value>1000</value>

</constructor-arg>

</bean>



###############:上面两种方式也可以写成下面的形式:


<bean
id="orderService"
class="cn.itcast.service.OrderServiceBean">

<constructor-arg index="0"
value=“xxx”/>//构造器注入

<property name=“name”
value=“zhao/>//属性setter方法注入


</bean>

3)设置注入(使用属性文件的)

在项目开发中,有时候要从一些配置文件中(properties)读取一些配置信息,如数据库的连接信息。在Spring程序中可以从不同的
properties中读取有用的信息。这里要用到
org.springframeword.beans.factory.config.PropertyPlaceholderConfigurer类,它是BeanFactoryPostProcessor的实现类.

下面例子:

项目结构:



connet.properties:

driver=mysql
username=yuan
password=test


test.properties:

1 age=12
2 height=13
3 weight=14


Connect.java装载着两个properties的信息:下面

public class Connect {

private
String driver;

private
String username;

private
String password;

int
age;

int
height;

int
weight;

//省略getter,setter

}

beans.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:p="http://www.springframework.org/schema/p"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="propertyConfigurer"

class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">


<property
name="locations">

<list>

<value>connect.properties</value>

<value>test.properties</value>

</list>

</property>


</bean>

<bean id="connect"
class="com.sunflower.yuan.Connect">

<property name="driver">

<value>${driver}</value>

</property>

<property name="username">

<value>${username}</value>

</property>

<property name="password">

<value>${password}</value>

</property>

<property name="age">

<value>${age}</value>

</property>

<property name="height">

<value>${height}</value>

</property>

<property name="weight">

<value>${weight}</value>

</property>

</bean>

</beans>

-------------------------------------------------------------

C、IOC之针对Bean不同类型[b]属性的不同注入的配置方式(基于B的依赖注入)[/b]

1)属性类型为8中基本数据类型以及其对应的包装类和String

<bean id="orderService"
class="cn.itcast.service.OrderServiceBean">

<constructor-arg index="0"
value=“xxx”/>//构造器注入

<property name=“name”
value=“zhao/>//属性setter方法注入


</bean>

2)属性为其他Bean类型

public class Order

{private Int id; private Customer
cust;....}

<bean id="custom"
class="cn.itcast.service.CustomBean">

<property name=“name”
value="zhao"/>//属性setter方法注入


</bean>

<bean id="order" class="cn.itcast.service.OrderBean">

<property
name=“id” value=1
/>


<property
name=“
cust”>

<ref
bean="custom">


</property>

</bean>

3)属性为null

<property name="name">

<null></null>

</property>

或者:

<property
name="name">

</null>

</property>

而不能如下配置(此时该属性不为null,而是空字符串):

<property name="name">

<value></value>

</property>

4)属性为集合类型


public class OrderServiceBean {

private
Set<String> sets = new
HashSet<String>();

private
List<String> lists = new
ArrayList<String>();

private
Properties properties = new Properties();

private
Map<String, String> maps = new
HashMap<String, String>();

....//这里省略属性的getter和setter方法

}

<bean id="order"
class="cn.itcast.service.OrderServiceBean">

<property name="lists">

<list>

<value>pkbest</value>

</list>


</property>

<property name="sets">

<set>

<value>pkbest</value>

</set>


</property>

<property name="maps">

<map>

<entry key=“pkbest"
value="28"/>

</map>


</property>

<property name="properties">

<props>

<prop
key=“pk">best</prop>

</props>


</property>

</bean>

5)关于使用的注解(Annotation
)方式为属性提供的依赖注入,请看下篇博文
-------------------------------------------------------------

D、Bean的作用域(基于B的依赖注入)


Bean的作用域共有5种:

single(单例)
:默认作用域,只在Spring容器加载时创建唯一的bean实例,因此当多次使用getBean方法返回实例,获得的都是同一个唯一实例。如果想对所有bean都应用延迟初始化,可以在根节点beans设置default-lazy-init=“true“,如下:

<beans
default-lazy-init="true“
...>

prototype(原型)
:每次使用该Bean都会创建新的实例,我们使用spring管理struts2的action时,所有action的Bean的作用域应该是此类型

request:表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP
request内有效

session:
表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP
session内有效

global
session
.不过它仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局Session的概念,它被所有构成某个portlet
web应用的各种不同的portlet所共享。

以上3种均基于web的Spring ApplicationContext情形下有效

例如:<bean id=“...”
class=“...”
scope=“prototype”/>

-------------------------------------------------------------

E、 Bean的初始化方法和销毁方法


<bean id="xxx"
class=“biz.OrderServiceBean" init-method="init"
destroy-method="close"
/>

public void init() {

System.out.println(“已经初始化了”);

}

public void close() {

System.out.println(“被销毁了”);

}

总结:IOC和DI的技术基础是基于反射技术和JavaBean的自省技术(自省技术的核心是反射技术)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: