ioc

IOC的概念,分类
1.IOC设计原则:高层的抽象的模块不应该倚赖于底层的具体实现,抽象不倚赖于实现
问题:耦合性高,不利于维护
对象的倚赖关系交给容器建立
解决:
对象的倚赖关系交给容器建立
在运行时动态地建立
IOC的特点:
1.模块之间的耦合性降低
2.利于测试
IOC的分类:如何实现IOC?
1.基于setter方法
2.基于构造器
Demo1:
IDevice.java
package ioc;
public interface IDevice {
public void print();
}

NetworkDevice.java
package ioc;
public class NetworkDevice implements IDevice {
public void print() {
System.out.println("NetworkDevice's print()");
}
}

PrinterDevice.java
package ioc;
public class PrinterDevice implements IDevice {
public void print() {
System.out.println("PrinterDevice's print()");
}
}

BankService.java
package ioc;
public class BankService {
private IDevice device;
// 1.基于setter方法
public void setDevice(IDevice dev) {
this.device = dev;
}
public void report() {
System.out.println("BankService's report()");
device.print();
}
}

Factory.java
package ioc;
public class Factory {
// 通过配置文件
private static Factory instance = new Factory();
private BankService bs = null;
private IDevice device = null;
private Factory() {
bs = new BankService();
String className = ConfigUtil.getValue(IDevice.class.getSimpleName());
try {
device = (IDevice)Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
bs.setDevice(device);
}

public static Factory getInstance() {
return instance;
}
public BankService getBankService() {
return bs;
}
}

ConfigUtil.java
package ioc;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class ConfigUtil {
private static Properties props = new Properties();
static {
InputStream ips = ConfigUtil.class.getClassLoader()
.getResourceAsStream("ioc/config.properties");
try {
props.load(ips);
} catch (IOException e) {
e.printStackTrace();
}
}
public static String getValue(String key) {
return props.getProperty(key);
}
public static void main(String[] args){
System.out.println(getValue("IDevice"));
}
}

config.properties
#IDevice=ioc.PrinterDevice
Idevice=ioc.NetworkDevice
Test.java
package ioc;
public class Test {
public static void main(String[] args){
BankService bankService = Factory.getInstance().getBankService();
bankService.report();
}
}
输出:
BankService's report()
NetworkDevice's print()
二.基本装配
IOC的基本使用
1.set方式的装配
2.构造器方式的装配
3.比较两种装配方式的区别
1.set方式的装配
(1).Bean类(pojo类)
(2).容器(Application Context)
(3).配置文件(*.xml)
常用的jar包:
spring/spring-framework-2.5.6/dist/spring.jar
spring/spring-framework-2.5.6/lib/cglib/cglib-nodep-2.1_3.jar
spring/spring-framework-2.5.6/lib/jakarta-commons
spring/spring-framework-2.5.6/aspectj标注时用到
spring/spring-framework-2.5.6/samples/jpetstore示例
spring/spring-framework-2.5.6/src源代码
Demo2:
第一步:建spring lib库
Window->Preferences->Java->Build Path->User Libraries->New
Spring2.0
把下面的jar包加到Spring2.0里面
spring/spring-framework-2.5.6/dist/spring.jar
spring/spring-framework-2.5.6/lib/cglib/cglib-nodep-2.1_3.jar
spring/spring-framework-2.5.6/lib/jakarta-commons
第二步:New Java Project (Project name:spring_ioc1)->Create separate source and output folders->ok
第三步:project->右键->MyEclipse->Add Spring Capabilities->(Spring2)User Libraries(spring2.0)-
>next->finish
在src下建立包ioc1.ioc1下建立类HelloBean.java和applicationContext.xml
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-2.0.xsd">
<!-- (1)bean的id属性必须是唯一标志,不能重复 ,(2)必须符合xml的规范,比如不
能包含"/",如果有用name属性来代替id属性,class对应的完整的类名(ioc1.HelloBean)
-->
<!---Bean类:(1)如果采用setter方式装配必须提供一个公开的不带参的构造器
(2)对于需要装配的属性必须提供对应的setter方法(采用setter方式装配)

(3)对于客户端的代码ClassPathXmlApplicationContext的类文件应依据classpath来存放
->
<bean id="helloBean" class="ioc1.HelloBean">
<!-- name对应类HelloBean的属性name-->
<property name="name">
<value>zs</value>
</property>
</bean>
</beans>
HelloBean.java
package ioc1;
/**
* Bean类
* @author wangxiuwei
* @date 2010.10.13
*/
public class HelloBean {
private String name;
public void setName(String name) {
this.name = name;
}
public String sayHello() {
return "hello" + name;
}
}
Test.java
package ioc1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 测试类
*@author wangxiuwei
* @date 2010.10.13
*/
public class Test {
public static void main(String[] args) {
// ioc1\\applicationContext.xml其中"\\"平台无关
// 构造了spring的容器,读取配置文件,
ApplicationContext ac = new ClassPathXmlApplicationContext(
"ioc1\\applicationContext.xml");
// 去找helloBean,根据id="helloBean" 找到class="ioc1.HelloBean",执行该类
// 并且把属性name="name" 的值 value=zs 通过setName给类赋值zs
HelloBean hb = (HelloBean) ac.getBean("helloBean");

// 找到后调用相应的方法
String str = hb.sayHello();
System.out.println(str);
}
}
Set方式装配
1.基本类型:8种基本类型 + 字符串
使用<value></value>元素
使用<property name="属性名">
<value>值</value>
</property>
<value>值</value>自动进行数据类型的转换
示例: (1)<property name="years">
<value>100</value>
</property>
此处也可以简化如下方式
(2)<property name="years" value="1000" />
2.对象类型的装配有如下三种方式
A <ref local>
B <ref bean>
C 直接嵌套
第一种情况
<!-- bean的id属性必须是唯一标志,不能重复 class对应的完整的类名 -->
//id="otherBean"与<ref local="otherBean" />
只在单前配置中查找
<bean id="otherBean" class="ioc2.otherBean">
<property name="obStr" value="String1"/>
</bean>
<bean id="someBean" class="ioc2.someBean">
<property name="ob">
<ref local="otherBean" />
</property>
</bean>
</beans>

对应的类中一定要有setXXX方法与该属性名对应
OtherBean SomeBean
只在当前配置文件中查找
第二种情况
<bean id="someBean" class="ioc2.SomeBean">
<property name="ob">
<bean id="otherBean" class="ioc2.OtherBean">
<property name="obStr" value="String1"/>
</bean>
</property>
</bean>
注:
1.不能够被客户端直接调用
2.某个Bean不希望被客户直接调用时,可以考虑把一个Bean定义在另外一个
Bean中
第三种情况
applicationContext.xml
<bean id="someBean" class="ioc2.SomeBean">
<property name="ob">
<ref bean="otherBean" />
</property>
</bean>
other.xml
<bean id="otherBean" class="ioc2.OtherBean">
<property name="obStr" value="String1"/>
</bean>
第四种情况
applicationContext.xml
<bean id="someBean" class="ioc2.SomeBean">
<!-- <property name="ob">
<ref bean="otherBean" />
</property>
与下面相同
-->
<property name="ob" ref="otherBean" />
</bean>
other.xml
<bean id="otherBean" class="ioc2.OtherBean">
<property name="obStr" value="String1"/>
</bean>
3.集合类型装配
List.Set,Map,Properties
applicationContext.xml
<bean id="someBean" class="ioc3.SomeBean">

<property name="listProperties">
<list>
<value>String1</value>
<value>String1</value>
<value>String3</value>
</list>
</property>
<property name="setProperties">
<set>
<value>String1</value>
<value>String1</value>
<value>String3</value>
</set>
</property>
<property name="mapProperties">
<map>
<entry key="mapKey">
<value>mapValue</value>
</entry>
</map>
</property>
<property name="props">
<props>
<prop key="propKey">propValue</prop>
</props>
</property>
</bean>
SomeBean.java
package ioc3;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class SomeBean {
private List listProperties;
private Set setProperties;
private Map mapProperties;
private Properties props;
public void setProps(Properties props) {
this.props = props;
}
public void setListProperties(List listProperties) {
this.listProperties = listProperties;
}
public void printInfo() {
System.out.println("listProperties:");
System.out.println(listProperties);
System.out.println("setProperties:");

System.out.println(setProperties);
System.out.println("mapProperties:");
System.out.println(mapProperties);
System.out.println("props:");
System.out.println(props);
}
public void setMapProperties(Map mapProperties) {
this.mapProperties = mapProperties;
}
public void setSetProperties(Set setProperties) {
this.setProperties = setProperties;
}
}
Test.java
package ioc3;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
// ioc2\\applicationContext.xml其中"\\"表示平台无关(不论是windows还是linux.unix都可以这样
用)
// 构造了spring的容器,读取配置文件,
ApplicationContext ac = new ClassPathXmlApplicationContext("ioc3\\applicationContext.xml");
SomeBean sb = (SomeBean) ac.getBean("someBean");
// 找到后调用相应的方法
sb.printInfo();
}
}
输出结果:
listProperties:
[String1, String1, String3]
setProperties:
[String1, String3]
mapProperties:
{mapKey=mapValue}
props:
{propKey=propValue}

2.构造器方式的装配
使用Constructor
applicationContext.xml
<bean id="otherBean" class="ioc4.OtherBean">
<property name="obStr">
<value>Andy</value>
</property>
</bean>
10
<bean id="someBean" class="ioc4.SomeBean">
<constructor-arg index="1">
<value>String1</value>
</constructor-arg>
<constructor-arg index="0">
<value>String2</value>
</constructor-arg>
<constructor-arg index="2">
<value>521521</value>
</constructor-arg>
<constructor-arg index="3">
<ref bean="otherBean" />
</constructor-arg>
</bean>

SomeBean.java
package ioc4;
public class SomeBean {
private String str1;
private String str2;
private int value1;
private OtherBean ob;
public SomeBean(String str1, String str2, int value1, OtherBean ob) {
// super();
this.str1 = str1;
this.str2 = str2;
this.value1 = value1;
this.ob = ob;
}
public void printInfo() {
System.out.println("str1: " + str1 + "str2: " + str2 + "value1: "
+ value1 + "ob: " + ob);
}
}
OtherBean.java
package ioc4;
11
public class OtherBean {
private String obStr;
public void setObStr(String obStr) {
this.obStr = obStr;
}
@Override
public String toString() {
return "OtherBean " + obStr;
}
}
Test.java
package ioc4;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext(
"ioc4\\applicationContext.xml");
SomeBean sb = (SomeBean) ac.getBean("someBean");
sb.printInfo();
}
}
要求:
1.Address采用构造器方式装配
2.person采用Set方式装配
3.打印personInfo
3 .set方式与constructor方式区别(有缺点<1>循环倚赖问题<2>属性很多,???????????构造器)
1.优先选set方式
2.bean的属性不错,
要求bean的属性在构造bean的实例时就已经完成装配,属性值在装配完后,就不再改变,
要求
Client通过Spring容器获得Bankservice实例,并且调用report()方法

三.复杂装配
1.Bean的定义的继承
Bean的配置信息可以复用
两个属性: 一是:abstract 两个值true,false,默认值是false
二是:parent
第一种情况:
1.配置文件applicationContext.xml
一般情况下保留abstract="true"
<bean id="abstractStudent" class="ioc7.Student" abstract="true">
<property name="className" value="sd0809" />
<property name="schoolName" value="tarena" />
</bean>
<bean id="student1" parent="abstractStudent">
<property name="name" value="张三" />
</bean>
<bean id="student2" parent="abstractStudent">
<property name="name" value="李四" />
</bean>
2.Student.java
package ioc7;
/**
* 学生类,采用setter方式进行装配
*
* @author wangxiuwei
* @date 2010.10.13
*/
public class Student {
@Override
public String toString() {
return name + " " + schoolName + " " + className;
}
private String name;
private String schoolName;
private String className;
public void setClassName(String className) {
this.className = className;
}
public void setName(String name) {
this.name = name;
}
public void setSchoolName(String schoolName) {
this.schoolName = schoolName;
}
}
3.Test.java
package ioc7;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 测试类
* @authorwangxiuwei
* @date 2010.10.13*/
public class Test {
public static void main(String[] args){
ApplicationContext ac = new
ClassPathXmlApplicationContext("ioc7\\applicationContext.xml");
Student stu = (Student)ac.getBean("student1");
// Student stu = (Student)ac.getBean("student2");
System.out.println(stu);
}
}
第二种情况:
<!-- 优化配置文件 -->
<bean id="abstractBean" abstract="true">
<property name="str1" value="string1" />
</bean>
<bean id="b" class="ioc7.B" parent="abstractBean">
<property name="value1" value="100" />
</bean>
<bean id="a" class="ioc7.A" parent="abstractBean">
<property name="amt" value="20.33" />
</bean>
2.Bean scoping(Bean的范围)
Spring容器如何去管理Bean的生命周期,它有Bean的范围决定
5种范围如下:
(1)singleton(单例模式)默认是单例模式
(2)prototype
每次调用getBean("myBean");返回的都是myBean对象类型的一个新创建的对象.
(3)request
在一次HTTP请求中,一个bean定义对应一个实例.
(4)session
在一个HTTPsession中,一个bean定义对应一个实例.
(5)global-session
在一个全局的HTTPsession中,一个bean定义对应一个实例.
3.Autowiring (自动装配)
手动装配:<property name="ob" ref="otherBean" />
自动装配:<bean id="someBean" autowire="byName">
Autowiring Properties(规则):
1.autowire="byName"
Bean identifier matches property name
:此选项将检查属性名并查找id值和其相同的bean,将其注入
2.autowire="byTpe"
Type matcher other defined bean
:如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配
3.autowire="constructor"
Match constructor argument types
4.autowire="autodetect"
Attempt by constructor,otherwise"type"如果有默认的缺省构造器,会先尝试
setter"byType",否则,有自定义的带参的构造器则去"Constructor"
Spring IOC容器可以自动装配互相协作bean之间的倚赖关系,也就是,通过使用autowire,我
们就不需要象前面的配置文件那样显示指定要注入的简单值或者bean,
15
SomeBean OtherBean
ob
细节:
1.手动装配与自动装配可以结合使用
2.自动装配方式有个缺点,容易出错,正式开发一般不用,适用于快速开发,
4.使用工厂方式创建Bean
实例工厂和静态工厂两种方式可以实现
5.Lifecycle Customization(组件的生命周期)
模版方法
回调
Thread t = new MyThread()
t.start()
回调加模版方法
实现了InitializingBean接口
或者通过init-method指定方法,允许容器在设置
好bean的所有必要属性后,调用接口方法或指定
方法进行初始化工作:同样,实现DisposableBean或者
通过destroy-method指定方法,允许在容器销毁该bean的时候
获得一次回调
Spring容器管理Bean一般过程:
step1:先实例化Bean(必须的)
step2:装配(可选的)
step3:回调方法(可选的包含了获取资源的方法[有很多])
step4:就绪(可以被调用)
step5:销毁(销毁之前如果有回调方法[释放资源]则执行)
ApplicationContext容器提供的接口
ApplicationContextAware接口
setApplicationContext()
要求:
Person p1 = new Person();
Car c1 = p1.getCar();
Person p2 = new Person();
Car c2 = p2.getCar();
初始化方法 回调接口

Thread
start()
run()
MyThread
run()
先申请资源
释放资源
回调类
控制类
Web容器
Servlet
Person
getCar() Car
Scope="singlton"
Scope="prototype"
car
Can define init method called after peoperties set
最后采用配置文件的方式或者标注的方式回调,最好不要使用接口回调
BeanPostProcessors(拦截器)
实现了BeanPostProcessors接口的Bean,称之为"后处理Bean"(扩展容器功能)
Bean已经实例化之后,实施"加工"
1.实例化 2.装配 3.回调(初始化)
step2:使用BFP修改已加载的配置
BeanPostProcesser
step1:加载
BeanFactoryPostProcessor当加载的类文件之后,实例化Bean之前,一般用来修改Bean
的配置
如果要在Spring容器完成bean的实例化,配置和其它的初始化后执行一些子定义逻辑,
可以加入一个或多个BeanPostProcessor实现.
6.Spring的事件处理(观察者模式)
java中
事件处理的好处:
1.可以实现一对多的
通信或调用
2.系统的耦合性低
编程的方式:做三件事情
step1:自定义事件 ApplicationEvent


Spring
的类
文件
容器
接口
监听器
按钮
事件
Spring容器
CustomerService
register()
CustomerListener
处理注册事件
1 先通过配置文件注册
2发布事件
事件
3抛给Listener
step2:开发监听器(必须实现Application Listener接口)
step3:要发布事件的Bean(组件)要实现ApplicationContextAware接口
再调用容器去发布事件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值