无意间在图书馆的旧楼发现了Spring2.0技术手册(一般是流通量较低的书会放在旧馆),记得之前网上对其评价还算不错,随便翻了下只能说很顺眼,相比国内的一些浮躁的作者(大部分是一些错误百出的培训机构拉的后腿),台湾人确实在写书方面略胜一筹,可惜识货的不多,李刚之流的人的书籍堆满了新馆的书架,谁叫他的书流通量大呢。准备整理些东西以便以后总结之用,虽然Spring已经出了3.0,但是对于我这种从未接触过框架技术的java准菜鸟来讲什么版本都不算老....囧,就此拙劣的记录一下自己或对或错的读书理解,如果有幸有朋友看到我的笔记,权当是与和我一样第一次接触Spring的同学们共勉,学习之路应该是有相通点的。

  

        Spring从基本功用来看,只是一个容器(想起tomcat这种Servlet容器,管理servlet以及其生命周期,对象之间的关系等等...仔细想想Spring管理的职责似乎也异曲同工),与其他框架类似,它通过现成的框架包精简了我们的代码量,更重要的是它实现了一个IoC容器(频繁出镜的词汇)。

何为IoC?

IoC(Inversion of Control)即控制反转,再多的措辞描述也只是一头雾水,用一个简单的例子来描述这个简单又重要的概念:
 

package luobo.test_one;

public class Father {             //Father类与Son类没有任何继承上的关系  
	private Son son=new Son();	  //为了有说服力,我使用了如此直接拙劣的对象注入
	private String name;             // 后面将会用到


	public Father(String name) { 
		this.name = name;
	}

	public void callSon() {
		System.out.println( son + "!\t你妈妈喊你回家吃饭");
	}

	public String toString() {
		return name;
	}
}
 



      Father类的callSon()将调用一个Son实例的toString()方法(覆盖自基类Object,我定义了Son类的toString()方法将返回Son的名字),形成了对Son类对象的依赖,这种依赖是直接主动的以及不可转变(除非你修改Father类,如果应用程序非常大,这将与在大型的依赖关系网中捅一个洞并无二样)的.对于应用程序的维护是极为不便的,试想如果又生了一个儿子呢?并且唐突的声明对某一个具体类的依赖也是错误的,试想如果贾君鹏其实是个女孩....或者贾君鹏只是别人的孩子,自然而然的你肯定会想到定义一个IChild接口,让需要被叫唤的孩子(无论你是侄子侄女抑或是孙女)实现这个接口:

package luobo.test_one;

public interface IChild {
	//需要的方法声明写在这里
}

 

而相应Father类修改如下:

package luobo.test_one;

public class Father {
	private IChild child;
	private String name; // 后面将会用到
	private String word;

	public Father() {

	}

	public Father(String name) { // 区别于IChild类型属性.使用构造方式注入 Type2 IoC
		this.name = name;
	}

	public void callChild() {
		System.out.println(this.toString() + "说: " + child + "!\t" + word);
	}

	public String toString() {
		return name;
	}

	public void setChild(IChild child) { // 使用setter getter方法注入 Type3 IoC
		this.child = child;
	}

	public IChild getChild() {
		return child;
	}

	public void setWord(String word) {
		this.word = word;
	}

	public String getWord() {
		return word;
	}

}


 

       但这样并没有完全形成IoC,仅仅只是解决了整个系统的重用性问题,简单的实现了依赖关系的转移(当然依赖于抽象是Spring的Ioc的核心理念之一),使得高层抽象模块与底层实现一定程度的松耦,Father类依赖于IChild以及String对象,并分别通过Setter以及构造函数所保留的接口(此接口非传统意义上的接口)来完成对象资源的注入。

  进而Spring可以通过设置来转变应用程序对其所需资源的的主动依赖,IoC容器帮助应用程序(如Father类)获取资源并注入它,整个过程Father类都是被动接受,修改相应的xml配置文件(此文件放在Eclipse工程的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" xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<bean id="father" class="luobo.test_one.Father">
		<constructor-arg>
			<value>ZhenJunpeng</value>
		</constructor-arg>
		<property name="word" value="你妈妈喊你回家吃饭"></property>
		<property name="child">
			<ref bean="son" />
		</property>

	</bean>
	<bean id="son" class="luobo.test_one.Son">
		<property name="name" value="JiaJunpeng"></property>
	</bean>
	
</beans>

注:在上面我们设置了Son类的一个bean,如果Son类只会被调用一次或者你不怕麻烦多次完成输入Son的全名也可以如下改变

<ref bean="son"/> =========><bean class="luobo.test_one.Son">

 

      所有的bean设置都已经完成了,万事俱备只欠东风,这时我们写一个callBack类调用father.callChild()来完成这次叫唤活动。  呃~然获得下面的输出结果是可想而知的:

null说: null! null

     

      我们忘记创建Spring框架内置的ApplicationContext对象来读取xml文件(虽然BeanFactory对象也能完成基本的容器管理功能,但是很显然ApplicationContext由于它支持的更多,两者的差距一言难尽,总之开始就使用ApplicationContex应该是个好习惯)来完成对象的依赖注入。

callBack.java修改如下

package luobo.test_one;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class callBack {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//通过ApplicationContext读取ClassPath路径下的xml文件,也可以以String[]的方式读取多个
		ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
		
		Father father = (Father)context.getBean("father");         //获取name为father的bean对象
		

		father.callChild();
	}

}

 

输出:

ZhenJunpeng说: JiaJunpeng! 你妈妈喊你回家吃饭。

      

      上面就是一个简单的IoC容器使用的例子,你之后可以方便的通过设置xml来实现对象间的依赖关系,而从各个类表面来看是完全看不出有任何的耦合性的,应用程序仅仅只是保留资源的进入方式(虚位以待),最终是由容器读取xml来实现资源的注入,Father完全处于被动状态(可以将容器想象为Mother),他并不清楚自己要去叫谁干什么。在容器的角度用一句概括:don’t ask me! i'll call you ...。

  

第一天备忘:

1)bean可通过<alias name="xxxx">设置别名 可通过别名获得此bean

2)通过<bean id="xxx" class="xxxxxxx.xxxx.xx" factory-bean="方法名">来指定静态工场方法来取得对象实例。

3)IoC的两种形式 Type 2(通过setter getter)与Type 3(通过构造函数注入) 各有特点。前者更形象,后者更直接

4)每一个Bean被取后默认只保持一个实例---singleton,即两次context.getBean("father")产生的对象只有一个。通过<bean id="xxx" class="xxxxxxx.xxxx.xx" scope=“[prototype]|[request]|[session]|[globalSession]">分别表示每次都产生一个新实例|请求阶段|会话阶段|应用程序阶段。

5)bean的定义可以继承 (注意:与类的继承目的性有相似但是本质上完全不同)对于多个类似属性设值一致的情形,可以考虑。

如<bean id="inheritedBean" abstract="true">它将不能被实例化 当然也可以设为普通的类

    .......................

 </bean>

 <bean id="someBean" class parent="inheritedBean">

.............................所有与父bean定义相同的属性值都一致 除非你重新设值覆盖。

6)在使用构造函数注入时候可以<construtor-arg index="0">的方式来指定第一个参数,以此类推

7)当没设置依赖关系但需要另一个bean在本类之前实例化的话可以引入depend-on="xxxxxx.xxxxx"属性

 

(写日志只花了1个半小时,编辑用了差不多5个多小时 最后下载了live writer才解决……)

posted on 2010-09-27 12:08  棍子上的萝卜  阅读(1015)  评论(0编辑  收藏  举报