今天来学习Spring,重点有四

    ①IoC(Inverse of Control)控制反转:指一个对象获取它所依赖对象的引用,这个责任被反转,由容器来帮助我们得到这个引用。

    ②DI(Dependency Injection)依赖注入:对象之间的依赖关系由Bean对象自己来处理,这样可以使得类之间达到更高层次的松耦合。

    ③面向接口编程:遵循"开闭原则",对于修改是关闭的,对于扩展是开放的。

    ④AOP(Aspect Oriant Programming)面向切面编程:弥补了面向对象编程的不足。

 

我们直接写个小例子,在例子中对此四点加以分析。

开发工具:eclipse for Jee,JDK1.6,Spring2.0。

首先引入jar包,spring.jar,commons-logging.jar,cglib-nodep-2.1.3.jar,aspectjrt.jar,aspectjweaver.jar。

 

新建工程,工程名Spring_base(任意),src下新建包,com.myPackage,src下新建bean.xml作为spring的配置文件。

 

首先建立老师类,接口名ITeacher,其中放入一个老师的方法teacherMethod(),代码如下:

package com.myPackage; public interface ITeacher { public void teacherMethod(); }

实现类类名:Teacher,代码如下:

package com.myPackage;

public class Teacher implements ITeacher {

	private String name;
	public void setName(String name){
		this.name=name;
	}
	public String getName(){
		return this.name;
	}
	
	private IBaseTemplate bt;
	public void setBt(IBaseTemplate bt){
		this.bt=bt;
	}
	public IBaseTemplate getBt(){
		return this.bt;
	}
	
	public void teacherMethod() {
		System.out.println("老师<"+name+">"+bt.baseMethod()+"留作业!");
	}

}

 

学生类:接口名IStudent,代码如下:

package com.myPackage; public interface IStudent { public void studentMethod(); }

学生实现类,类名Student,代码如下:

package com.myPackage;

public class Student implements IStudent {

	public Student() {
	}

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

	private String name;

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return this.name;
	}

	private IBaseTemplate bt;

	public void setBt(IBaseTemplate bt) {
		this.bt = bt;
	}

	public IBaseTemplate getBt() {
		return this.bt;
	}

	private Birthday birthday;

	public void setBirthday(Birthday birthday) {
		this.birthday = birthday;
	}

	public Birthday getBirthday() {
		return this.birthday;
	}

	public void studentMethod() {
		System.out.println(birthday+"出生的学生<" + name + ">" + bt.baseMethod() + "做作业!");
	}

}

学生类中引用了生日类,生日类类名:Birthday,代码如下:

package com.myPackage;

public class Birthday {

	private int year;
	private int month;
	private int day;

	public Birthday(int year, int month, int day) {
		this.year = year;
		this.month = month;
		this.day = day;
	}

	public void setDay(int day) {
		this.day = day;
	}

	@Override
	public String toString() {
		return year + "-" + month + "-" + day;
	}
}

老师和学生类中都引用到了BaseTemplate,这个类抽离了学生类和老师类中都要用到的共通属性,为了表示bean定义的继承关系而写,接口名:IBaseTemplate,代码如下:

package com.myPackage;

public interface IBaseTemplate {
	public String baseMethod();
}

实现类类名:BaseTemplate,代码如下:

package com.myPackage;

public class BaseTemplate implements IBaseTemplate {

	@Override
	public String baseMethod() {
		return "..疯狂的..";
	}

}

然后建立面向切面编程的类,类名AOP,代码如下:

package com.myPackage;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class AOP {
	
	@Before("execution(* *.studentMethod(..))")
	public void dispHint(){
		System.out.println("*************这是在执行学生方法前**************");
	}
}

最后是测试类Test,代码如下:

package com.myPackage;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"bean.xml"});
		
		//老师
		ITeacher tea = (ITeacher)ac.getBean("teacher");
		tea.teacherMethod();
		ITeacher tea22 = (ITeacher)ac.getBean("teacher");
		tea22.teacherMethod();
		
		Teacher tea1 = (Teacher)ac.getBean("teacher");
		tea1.setName("hahaha");
		tea1.teacherMethod();
		Teacher tea2 = (Teacher)ac.getBean("teacher");
		tea2.setName("heihei");
		tea2.teacherMethod();
		if(tea22==tea)
			System.out.println("true");
		else
			System.out.println("false");

		//学生
		IStudent stu = (IStudent)ac.getBean("student");
		stu.studentMethod();
		
		//学生2
		IStudent stu2 = (IStudent)ac.getBean("student2");
		stu2.studentMethod();
	}

}

bean.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:aop="http://www.springframework.org/schema/aop"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans 
				        http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
				        http://www.springframework.org/schema/aop
				        http://www.springframework.org/schema/aop/spring-aop-2.0.xsd " >

	<!-- template类 -->
	<bean id="template" class="com.myPackage.BaseTemplate" />
	<!-- 模板类 -->
	<bean id="base" abstract="true">
		<property name="bt" ref="template"></property>
	</bean>
	
	<!-- 老师类 -->
	<bean id="teacher" class="com.myPackage.Teacher" parent="base"
		scope="singleton">
		<property name="name" value="刘作业"></property>
	</bean>
	
	<!-- 学生类 -->
	<bean id="student" class="com.myPackage.Student" parent="base"
		scope="prototype">
		<property name="name" value="左作业"></property>
		<property name="birthday" ref="bir"></property>
	</bean>
	<!-- 学生类2 -->
	<bean id="student2" class="com.myPackage.Student" parent="base"
		scope="prototype">
		<constructor-arg index="0" value="左作业"></constructor-arg>
	</bean>
	
	<!-- 生日类 -->
	<bean id="bir" class="com.myPackage.Birthday">
		<constructor-arg index="0" value="2000"></constructor-arg>
		<constructor-arg index="1" value="8"></constructor-arg>
		<constructor-arg index="2" value="8"></constructor-arg>
	</bean>
	
	
	<bean id="aop" class="com.myPackage.AOP"/>
	<!-- AspectJ自动代理找程序中的注解 -->
	<aop:aspectj-autoproxy />
</beans>


运行as a Java Application,得到结果为:

老师<刘作业>..疯狂的..留作业! 老师<hahaha>..疯狂的..留作业! 老师<heihei>..疯狂的..留作业! true *************这是在执行学生方法前************** 2000-8-8出生的学生<左作业>..疯狂的..做作业! *************这是在执行学生方法前************** null出生的学生<左作业>..疯狂的..做作业! 


从结果我们分析,

第一句输出:"老师<刘作业>..疯狂的..留作业!",我们看bean.xml里的老师类下的内容,我们通过Spring容器,实现了重点中的IoC,也就是通过spring容器来创造的这个对象,使用了DI中的setting注入,而且是面向接口的编程(ITeacher),scope="singleton"这一句是为了让类的实例化为单例模式,而这正是业务层需要的,因此我们看到第四句的输出是true,也就是通过(ITeacher)的方式造出来的两个实例其实是同一个实例。

第五句第7句的输出:*************这是在执行学生方法前**************,正是运用了AOP,在学生方法的执行之前,就加上这一句的输出处理,这里AOP的方式有很多种,之前执行,之后执行,环绕执行等,这里我们只是做简单了解。

依赖注入的方法有setting,构造子注入,当然我们不仅可以注入基本类型的值,还可以注入具有依赖关系的对象,譬如这句的输出:2000-8-8出生的学生<左作业>..疯狂的..做作业!,中的生日我们就是这么做的,<property name="birthday" ref="bir"></property>这一句就是对对象的依赖注入,而bir又使用了构造子注入的方式。