Spring入门
来源:百度文库 编辑:16楼社区 时间:2021/01/26 11:27:20
作者:Xuefeng 文章来源:本站原创 点击数:656 更新时间:2006-4-2
提示:如果您有任何疑问,请到开发论坛提问或讨论。
Spring是一个非常优秀的轻量级框架,通过Spring的IoC容器,我们的关注点便放到了需要实现的业务逻辑上。对AOP的支持则能让我们动态增强业务方法。编写普通的业务逻辑Bean是非常容易而且易于测试的,因为它能脱离J2EE容器(如Servlet,JSP环境)单独进行单元测试。最后的一步便是在Spring框架中将这些业务Bean以XML配置文件的方式组织起来,它们就按照我们预定的目标正常工作了!非常容易!
本文将给出一个基本的Spring入门示例,并演示如何使用Spring的AOP将复杂的业务逻辑分离到每个方面中。
1.开发环境配置
2.编写Bean接口及其实现
3.在Spring中配置Bean并获得Bean的实例
4.编写Advisor以增强ServiceBean
5.总结
1.开发环境配置
首先,需要正确配置Java环境。推荐安装JDK1.4.2,并正确配置环境变量:
JAVA_HOME=
CLASSPATH=.
Path=%JAVA_HOME%\bin;……
我们将使用免费的Eclipse 3.1作为IDE。新建一个Java Project,将Spring的发布包spring.jar以及commons-logging-1.0.4.jar复制到Project目录下,并在Project > Properties中配置好Java Build Path:

2.编写Bean接口及其实现
我们实现一个管理用户的业务Bean。首先定义一个ServiceBean接口,声明一些业务方法:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
* For more information, please visit:http://www.crackj2ee.com
*/
package com.crackj2ee.example.spring; /**
* Interface of service facade.
*
* @author Xuefeng
*/
public interface ServiceBean {
void addUser(String username, String password);
void deleteUser(String username);
boolean findUser(String username);
String getPassword(String username);
}
然后在MyServiceBean中实现接口:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
*
* For more information, please visit:http://www.crackj2ee.com
*/
package com.crackj2ee.example.spring; import java.util.*; public class MyServiceBean implements ServiceBean { private String dir;
private Map map = new HashMap(); public void setUserDir(String dir) {
this.dir = dir;
System.out.println("Set user dir to: " + dir);
} public void addUser(String username, String password) {
if(!map.containsKey(username))
map.put(username, password);
else
throw new RuntimeException("User already exist.");
} public void deleteUser(String username) {
if(map.remove(username)==null)
throw new RuntimeException("User not exist.");
} public boolean findUser(String username) {
return map.containsKey(username);
} public String getPassword(String username) {
return (String)map.get(username);
}
}
为了简化逻辑,我们使用一个Map保存用户名和口令。
现在,我们已经有了一个业务Bean。要测试它非常容易,因为到目前为止,我们还没有涉及到Spring容器,也没有涉及到任何Web容器(假定这是一个Web应用程序关于用户管理的业务Bean)。完全可以直接进行Unit测试,或者,简单地写个main方法测试:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
* For more information, please visit:http://www.crackj2ee.com
*/
package com.crackj2ee.example.spring; public class Main { public static void main(String[] args) throws Exception {
ServiceBean service = new MyServiceBean();
service.addUser("bill", "hello");
service.addUser("tom", "goodbye");
service.addUser("tracy", "morning");
System.out.println("tom‘s password is: " + service.getPassword("tom"));
if(service.findUser("tom")) {
service.deleteUser("tom");
}
}
}
执行结果:

3.在Spring中配置Bean并获得Bean的实例
我们已经在一个main方法中实现了业务,不过,将对象的生命周期交给容器管理是更好的办法,我们就不必为初始化对象和销毁对象进行硬编码,从而获得更大的灵活性和可测试性。
想要把ServiceBean交给Spring来管理,我们需要一个XML配置文件。新建一个beans.xml,放到src目录下,确保在classpath中能找到此配置文件,输入以下内容:
"http://www.springframework.org/dtd/spring-beans.dtd">
以上XML声明了一个id为service的Bean,默认地,Spring为每个声明的Bean仅创建一个实例,并通过id来引用这个Bean。下面,我们修改main方法,让Spring来管理业务Bean:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
* For more information, please visit:http://www.crackj2ee.com
*/
package com.crackj2ee.example.spring; import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource; public class Main { public static void main(String[] args) throws Exception {
// init factory:
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
// use service bean:
ServiceBean service = (ServiceBean)factory.getBean("service");
service.addUser("bill", "hello");
service.addUser("tom", "goodbye");
service.addUser("tracy", "morning");
System.out.println("tom‘s password is \"" + service.getPassword("tom") + "\"");
if(service.findUser("tom")) {
service.deleteUser("tom");
}
// close factory:
factory.destroySingletons();
}
}
执行结果:

由于我们要通过main方法启动Spring环境,因此,首先需要初始化一个BeanFactory。红色部分是初始化Spring的BeanFactory的典型代码,只需要保证beans.xml文件位于classpath中。
然后,在BeanFactory中通过id查找,即可获得相应的Bean的实例,并将其适当转型为合适的接口。
接着,实现一系列业务操作,在应用程序结束前,让Spring销毁所有的Bean实例。
对比上一个版本的Main,可以看出,最大的变化是不需要自己管理Bean的生命周期。另一个好处是在不更改实现类的前提下,动态地为应用程序增加功能。
4.编写Advisor以增强ServiceBean
所谓AOP即是将分散在各个方法处的公共代码提取到一处,并通过类似拦截器的机制实现代码的动态织入。可以简单地想象成,在某个方法的调用前、返回前、调用后和抛出异常时,动态插入自己的代码。在弄清楚Pointcut、Advice之类的术语前,不如编写一个最简单的AOP应用来体验一下。
考虑一下通常的Web应用程序都会有日志记录,我们来编写一个LogAdvisor,对每个业务方法调用前都作一个记录:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
* For more information, please visit:http://www.crackj2ee.com
*/
package com.crackj2ee.example.spring; import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice; public class LogAdvisor implements MethodBeforeAdvice {
public void before(Method m, Object[] args, Object target) throws Throwable {
System.out.println("[Log] " + target.getClass().getName() + "." + m.getName() + "()");
}
}
然后,修改beans.xml:
"http://www.springframework.org/dtd/spring-beans.dtd">
com.crackj2ee.example.spring.ServiceBean
注意观察修改后的配置文件,我们使用了一个ProxyFactoryBean作为service来与客户端打交道,而真正的业务Bean即MyServiceBean被声明为serviceTarget并作为参数对象传递给ProxyFactoryBean,proxyInterfaces指定了返回的接口类型。对于客户端而言,将感觉不出任何变化,但却动态加入了LogAdvisor,关系如下:

运行结果如下,可以很容易看到调用了哪些方法:

要截获指定的某些方法也是可以的。下面的例子将修改getPassword()方法的返回值:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
* For more information, please visit:http://www.crackj2ee.com
*/
package com.crackj2ee.example.spring; import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; public class PasswordAdvisor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
Object ret = invocation.proceed();
if(ret==null)
return null;
String password = (String)ret;
StringBuffer encrypt = new StringBuffer(password.length());
for(int i=0; iencrypt.append(‘*‘);
return encrypt.toString();
}
}
这个PasswordAdvisor将截获ServiceBean的getPassword()方法的返回值,并将其改为"***"。继续修改beans.xml:
"http://www.springframework.org/dtd/spring-beans.dtd">
com.crackj2ee.example.spring.ServiceBean
利用Spring提供的一个RegexMethodPointcutAdvisor可以非常容易地指定要截获的方法。运行结果如下,可以看到返回结果变为"******":

还需要继续增强ServiceBean?我们编写一个ExceptionAdvisor,在业务方法抛出异常时能做一些处理:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
* For more information, please visit:http://www.crackj2ee.com
*/
package com.crackj2ee.example.spring; import org.springframework.aop.ThrowsAdvice; public class ExceptionAdvisor implements ThrowsAdvice {
public void afterThrowing(RuntimeException re) throws Throwable {
System.out.println("[Exception] " + re.getMessage());
}
}
将此Advice添加到beans.xml中,然后在业务Bean中删除一个不存在的用户,故意抛出异常:
service.deleteUser("not-exist");
再次运行,注意到ExceptionAdvisor记录下了异常:

5.总结
利用Spring非常强大的IoC容器和AOP功能,我们能实现非常灵活的应用,让Spring容器管理业务对象的生命周期,利用AOP增强功能,却不影响业务接口,从而避免更改客户端代码。
为了实现这一目标,必须始终牢记:面向接口编程。而Spring默认的AOP代理也是通过Java的代理接口实现的。虽然Spring也可以用CGLIB实现对普通类的代理,但是,业务对象只要没有接口,就会变得难以扩展、维护和测试。
欢迎来信与作者交流:asklxf@163.com
可以从此处下载完整的Eclipse工程:
springbasic.rar
_xyz
提示:如果您有任何疑问,请到开发论坛提问或讨论。
Spring是一个非常优秀的轻量级框架,通过Spring的IoC容器,我们的关注点便放到了需要实现的业务逻辑上。对AOP的支持则能让我们动态增强业务方法。编写普通的业务逻辑Bean是非常容易而且易于测试的,因为它能脱离J2EE容器(如Servlet,JSP环境)单独进行单元测试。最后的一步便是在Spring框架中将这些业务Bean以XML配置文件的方式组织起来,它们就按照我们预定的目标正常工作了!非常容易!
本文将给出一个基本的Spring入门示例,并演示如何使用Spring的AOP将复杂的业务逻辑分离到每个方面中。
1.开发环境配置
2.编写Bean接口及其实现
3.在Spring中配置Bean并获得Bean的实例
4.编写Advisor以增强ServiceBean
5.总结
1.开发环境配置
首先,需要正确配置Java环境。推荐安装JDK1.4.2,并正确配置环境变量:
JAVA_HOME=
CLASSPATH=.
Path=%JAVA_HOME%\bin;……
我们将使用免费的Eclipse 3.1作为IDE。新建一个Java Project,将Spring的发布包spring.jar以及commons-logging-1.0.4.jar复制到Project目录下,并在Project > Properties中配置好Java Build Path:

2.编写Bean接口及其实现
我们实现一个管理用户的业务Bean。首先定义一个ServiceBean接口,声明一些业务方法:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
* For more information, please visit:http://www.crackj2ee.com
*/
package com.crackj2ee.example.spring; /**
* Interface of service facade.
*
* @author Xuefeng
*/
public interface ServiceBean {
void addUser(String username, String password);
void deleteUser(String username);
boolean findUser(String username);
String getPassword(String username);
}
然后在MyServiceBean中实现接口:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
*
* For more information, please visit:http://www.crackj2ee.com
*/
package com.crackj2ee.example.spring; import java.util.*; public class MyServiceBean implements ServiceBean { private String dir;
private Map map = new HashMap(); public void setUserDir(String dir) {
this.dir = dir;
System.out.println("Set user dir to: " + dir);
} public void addUser(String username, String password) {
if(!map.containsKey(username))
map.put(username, password);
else
throw new RuntimeException("User already exist.");
} public void deleteUser(String username) {
if(map.remove(username)==null)
throw new RuntimeException("User not exist.");
} public boolean findUser(String username) {
return map.containsKey(username);
} public String getPassword(String username) {
return (String)map.get(username);
}
}
为了简化逻辑,我们使用一个Map保存用户名和口令。
现在,我们已经有了一个业务Bean。要测试它非常容易,因为到目前为止,我们还没有涉及到Spring容器,也没有涉及到任何Web容器(假定这是一个Web应用程序关于用户管理的业务Bean)。完全可以直接进行Unit测试,或者,简单地写个main方法测试:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
* For more information, please visit:http://www.crackj2ee.com
*/
package com.crackj2ee.example.spring; public class Main { public static void main(String[] args) throws Exception {
ServiceBean service = new MyServiceBean();
service.addUser("bill", "hello");
service.addUser("tom", "goodbye");
service.addUser("tracy", "morning");
System.out.println("tom‘s password is: " + service.getPassword("tom"));
if(service.findUser("tom")) {
service.deleteUser("tom");
}
}
}
执行结果:

3.在Spring中配置Bean并获得Bean的实例
我们已经在一个main方法中实现了业务,不过,将对象的生命周期交给容器管理是更好的办法,我们就不必为初始化对象和销毁对象进行硬编码,从而获得更大的灵活性和可测试性。
想要把ServiceBean交给Spring来管理,我们需要一个XML配置文件。新建一个beans.xml,放到src目录下,确保在classpath中能找到此配置文件,输入以下内容:
"http://www.springframework.org/dtd/spring-beans.dtd">
以上XML声明了一个id为service的Bean,默认地,Spring为每个声明的Bean仅创建一个实例,并通过id来引用这个Bean。下面,我们修改main方法,让Spring来管理业务Bean:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
* For more information, please visit:http://www.crackj2ee.com
*/
package com.crackj2ee.example.spring; import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource; public class Main { public static void main(String[] args) throws Exception {
// init factory:
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
// use service bean:
ServiceBean service = (ServiceBean)factory.getBean("service");
service.addUser("bill", "hello");
service.addUser("tom", "goodbye");
service.addUser("tracy", "morning");
System.out.println("tom‘s password is \"" + service.getPassword("tom") + "\"");
if(service.findUser("tom")) {
service.deleteUser("tom");
}
// close factory:
factory.destroySingletons();
}
}
执行结果:

由于我们要通过main方法启动Spring环境,因此,首先需要初始化一个BeanFactory。红色部分是初始化Spring的BeanFactory的典型代码,只需要保证beans.xml文件位于classpath中。
然后,在BeanFactory中通过id查找,即可获得相应的Bean的实例,并将其适当转型为合适的接口。
接着,实现一系列业务操作,在应用程序结束前,让Spring销毁所有的Bean实例。
对比上一个版本的Main,可以看出,最大的变化是不需要自己管理Bean的生命周期。另一个好处是在不更改实现类的前提下,动态地为应用程序增加功能。
4.编写Advisor以增强ServiceBean
所谓AOP即是将分散在各个方法处的公共代码提取到一处,并通过类似拦截器的机制实现代码的动态织入。可以简单地想象成,在某个方法的调用前、返回前、调用后和抛出异常时,动态插入自己的代码。在弄清楚Pointcut、Advice之类的术语前,不如编写一个最简单的AOP应用来体验一下。
考虑一下通常的Web应用程序都会有日志记录,我们来编写一个LogAdvisor,对每个业务方法调用前都作一个记录:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
* For more information, please visit:http://www.crackj2ee.com
*/
package com.crackj2ee.example.spring; import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice; public class LogAdvisor implements MethodBeforeAdvice {
public void before(Method m, Object[] args, Object target) throws Throwable {
System.out.println("[Log] " + target.getClass().getName() + "." + m.getName() + "()");
}
}
然后,修改beans.xml:
"http://www.springframework.org/dtd/spring-beans.dtd">
注意观察修改后的配置文件,我们使用了一个ProxyFactoryBean作为service来与客户端打交道,而真正的业务Bean即MyServiceBean被声明为serviceTarget并作为参数对象传递给ProxyFactoryBean,proxyInterfaces指定了返回的接口类型。对于客户端而言,将感觉不出任何变化,但却动态加入了LogAdvisor,关系如下:

运行结果如下,可以很容易看到调用了哪些方法:

要截获指定的某些方法也是可以的。下面的例子将修改getPassword()方法的返回值:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
* For more information, please visit:http://www.crackj2ee.com
*/
package com.crackj2ee.example.spring; import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; public class PasswordAdvisor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
Object ret = invocation.proceed();
if(ret==null)
return null;
String password = (String)ret;
StringBuffer encrypt = new StringBuffer(password.length());
for(int i=0; i
return encrypt.toString();
}
}
这个PasswordAdvisor将截获ServiceBean的getPassword()方法的返回值,并将其改为"***"。继续修改beans.xml:
"http://www.springframework.org/dtd/spring-beans.dtd">
利用Spring提供的一个RegexMethodPointcutAdvisor可以非常容易地指定要截获的方法。运行结果如下,可以看到返回结果变为"******":

还需要继续增强ServiceBean?我们编写一个ExceptionAdvisor,在业务方法抛出异常时能做一些处理:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
* For more information, please visit:http://www.crackj2ee.com
*/
package com.crackj2ee.example.spring; import org.springframework.aop.ThrowsAdvice; public class ExceptionAdvisor implements ThrowsAdvice {
public void afterThrowing(RuntimeException re) throws Throwable {
System.out.println("[Exception] " + re.getMessage());
}
}
将此Advice添加到beans.xml中,然后在业务Bean中删除一个不存在的用户,故意抛出异常:
service.deleteUser("not-exist");
再次运行,注意到ExceptionAdvisor记录下了异常:

5.总结
利用Spring非常强大的IoC容器和AOP功能,我们能实现非常灵活的应用,让Spring容器管理业务对象的生命周期,利用AOP增强功能,却不影响业务接口,从而避免更改客户端代码。
为了实现这一目标,必须始终牢记:面向接口编程。而Spring默认的AOP代理也是通过Java的代理接口实现的。虽然Spring也可以用CGLIB实现对普通类的代理,但是,业务对象只要没有接口,就会变得难以扩展、维护和测试。
欢迎来信与作者交流:asklxf@163.com
可以从此处下载完整的Eclipse工程:
springbasic.rar
_xyz
Spring入门
Spring入门
Spring入门
Spring入门
Spring入门
Spring入门
Spring入门
Spring入门
spring入门编程
Spring MVC 入门
Spring MVC 入门
Spring MVC 入门
Spring MVC 入门
Spring入门经典一
spring 入门经典二
Spring MVC 入门
Spring入门经典一
spring 入门经典二
Struts+Spring+Hibernate快速入门
struts+spring+hibernate快速入门
Struts+Spring+Hibernate快速入门
【Struts+Spring+Hibernate快速入门】
【Struts+Spring+Hibernate快速入门】
Struts+Spring+Hibernate快速入门