SpringInAction笔记(一) —— Spring之旅

      spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架,主要是针对javaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以和Struts框架,ibatis框架等组合使用。
       Spring存在原因即它简化和java开发,为了降低Java开发的复杂性,Spring采取了以下4种关键策略:
       1、基于POJO的轻量级和最小侵入性编程。
       2、通过依赖注入和面向接口实现松耦合。
       3、基于切面和惯例进行声明式编程。
       4、通过切面和模板减少样板式代码。

1、轻量级和最小侵入性的POJO
   很多框架通过强迫应用继承它们的类工实现它们的接口从而让应用跟框架绑死。在Spring普及之前,常用的框架有EJB。典型的例子即,EJB2的无状态会话Bean,Java bean实现SessionBean接口,它强迫你参与EJB的生命周期。使得JavaBean很大一部分多余代码为使用EJB而编写。
   使用Spring,JavaBean不需要实现、继承或者导入与Spring API相关的任何东西。Spring通过依赖注入来装配POJO,使应用对象彼此之间保持松散耦合。

2、通过依赖注入和面向接口实现松耦合
        任何一个有实现意义的应用都是由两个或者更多的类组成,这些类相互之间进行协作来完成特定的业务逻辑。通常,每个对象负责管理与自己相互协作的对象的引用,这将会导致

高度耦合和难以测试的代码。

我们以骑士(Knight)执行探险任务(Quest)为例,如拯救少女,击杀恶龙.....等。新建Web工程SpringInAction,添加Spring支持

清单1  骑士接口Knight.java:

package com.springinaction.ch01;

/**
 * 骑士接口
 * @author lenovo
 *
 */
public interface Knight {

	/**
	 * 执行各种任务
	 */
	void embarkOnQuest();

}
清单2   探险任务接口 Quest.java: 
 

package com.springinaction.ch01;

/**
 * 探险任务
 * @author lenovo
 *
 */
public interface Quest {
	
	void embark();

}

清单3  骑士实现 BraveKnight.java

package com.springinaction.ch01;
  
public class BraveKnight implements Knight {
  
	private Quest quest;

	public BraveKnight(Quest quest) {  
		this.quest = quest;
	}
  
	public void embarkOnQuest() {
		quest.embark(); 
	}

}

清单4 使用Mockito框架测试BraveKnight,需添加mockito-all-1.10.19.jar、JUnit4库

package com.springinaction.ch01.test;
import static org.mockito.Mockito.*;

import org.junit.Test;

import com.springinaction.ch01.BraveKnight;
import com.springinaction.ch01.Quest;

public class BraveKnightTest {
	
	@Test
	public void knightShouldEmbarkOnQuest() {
		//模拟的创建,对接口进行模拟 
		Quest mockQuest = mock(Quest.class);
		BraveKnight knight = new BraveKnight(mockQuest);
		knight.embarkOnQuest();
		//验证Quest接口的方法embark仅调用一次
		verify(mockQuest, times(1)).embark();
	}

}

使用mock框架Mockito去创建一个Quest接口的mock实现。通过这个mock对象,就可以创建一个新的BraveKnight实例,并通过构造器注入这个mockQuest。当调用embarkOnQuset方法时,就可以要求Mockito框架验证Quest的mock实现方法仅仅被调用一次。


清单5  探险任务实现SlayDragonQuest.java

package com.springinaction.ch01;

import java.io.PrintStream;

public class SlayDragonQuest implements Quest {
	
	private PrintStream stream;
	
	/**
	 * 击杀恶龙任务 
	 * @param stream
	 */
	public SlayDragonQuest(PrintStream stream) {
		this.stream = stream;
	}
	
	public void embark() {
		stream.println("Embarking on quest to slay the dragon!");
	}

}


清单6  添加一个吟游诗人歌唱骑士的事迹Minstrel.java

package com.springinaction.ch01;

import java.io.PrintStream;

/**
 * 吟游诗人
 * @author lenovo
 *
 */
public class Minstrel {
	
	private PrintStream stream;
	
	public Minstrel(PrintStream stream) {
		this.stream = stream;
	}
	
	//探险任务之前执行
	public void singBeforeQuest() {
		stream.println("Fa la la, the knight is so brave!");
	}

	//探险任务之后执行
	public void singAfterQuest() { 
		stream.println("Tee hee hee, the brave knight did embark on a quest!");
	}

}

清单7  配置文件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"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	   http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
	   http://www.springframework.org/schema/aop
	   http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
	   ">
	
	<bean id="knight" class="com.springinaction.ch01.BraveKnight">
	    <constructor-arg ref="quest"></constructor-arg>
	</bean>
	
	<bean id="quest" class="com.springinaction.ch01.SlayDragonQuest">
	    <constructor-arg value="#{T(System).out}"></constructor-arg>
	</bean>
	
	<bean id="minstrel" class="com.springinaction.ch01.Minstrel">
	    <constructor-arg value="#{T(System).out}"></constructor-arg>
	</bean>
	
	<aop:config>
	    <aop:aspect ref="minstrel">
	        <!-- 定义切点 -->
	        <aop:pointcut expression="execution(* *.embarkOnQuest(..))" id="embark"/>
	        
	        <aop:before pointcut-ref="embark" method="singBeforeQuest"/>
	        <aop:after pointcut-ref="embark" method="singAfterQuest"/>
	    </aop:aspect>
	</aop:config>

</beans>
 <constructor-arg value="#{T(System).out}"></constructor-arg>中 #{}是SPEL表达式,作用是通过spring把值注入给某个属性 SpEL提供了一个特殊的运算符:T(),这个运算符用于告诉SpEL将该运算符内的字符串当成“类”处理,避免Spring对其进行其他解析。注意:T()运算符使用java.lang包下的类时可以省略包名,但使用其他包下的所有类时应使用全限定类名。".out"表示调用类的方法,与在Java代码中调用方法没有任何区别。

expression="execution(* *.embarkOnQuest(..))
第一个*,通配 方法返回的任意类型
第二个*,通配 任何包含embarkOnQuest方法的类
第三个(..),括号中的两点表示任意个参数,包括0个

清单8  测试类:
package com.springinaction.ch01;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class KnightMain {
	
	public static void main(String[] args) throws Exception {
		
		/*
		//XmlBeanFactory不支持AOP,也不支持pel表达式
		DefaultListableBeanFactory factory= new DefaultListableBeanFactory ();
		XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
		reader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
		
		Knight knight = (Knight) factory.getBean("knight");
		knight.embarkOnQuest();
		factory.destroySingletons();
		*/
		
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Knight knight = (Knight) context.getBean("knight"); //获取bean  
		knight.embarkOnQuest(); //使用bean  
		context.close();
		
  }
}
注意:这里使用ClassPathXmlApplicationContext 加载配置文件,而不使用DefaultListableBeanFactory ,因为XmlBeanFactory不支持AOP,也不支持pel表达式。
运行结果:
SpringInAction笔记(一) - 叶主任 - 叶主任的博客

猜你喜欢

转载自blog.csdn.net/ganmaotong/article/details/80373035