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=<JDK安装目录>
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.javaeedev.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
*/
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
*/
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中能找到此配置文件,输入以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="service" class="com.crackj2ee.example.spring.MyServiceBean" />
</beans>
以上XML声明了一个id为service的Bean,默认地,Spring为每个声明的Bean仅创建一个实例,并通过id来引用这个Bean。下面,我们修改main方法,让Spring来管理业务Bean:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
*/
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
*/
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:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="serviceTarget" class="com.crackj2ee.example.spring.MyServiceBean" />
<bean id="logAdvisor" class="com.crackj2ee.example.spring.LogAdvisor" />
<bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces"><value>com.crackj2ee.example.spring.ServiceBean</value></property>
<property name="target"><ref local="serviceTarget"/></property>
<property name="interceptorNames">
<list>
<value>logAdvisor</value>
</list>
</property>
</bean>
</beans>
注意观察修改后的配置文件,我们使用了一个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<password.length(); i++)
encrypt.append('*');
return encrypt.toString();
}
}
这个PasswordAdvisor将截获ServiceBean的getPassword()方法的返回值,并将其改为"***"。继续修改beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="serviceTarget" class="com.crackj2ee.example.spring.MyServiceBean" />
<bean id="logAdvisor" class="com.crackj2ee.example.spring.LogAdvisor" />
<bean id="passwordAdvisorTarget" class="com.crackj2ee.example.spring.PasswordAdvisor" />
<bean id="passwordAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref local="passwordAdvisorTarget"/>
</property>
<property name="patterns">
<list>
<value>.*getPassword</value>
</list>
</property>
</bean>
<bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces"><value>com.crackj2ee.example.spring.ServiceBean</value></property>
<property name="target"><ref local="serviceTarget"/></property>
<property name="interceptorNames">
<list>
<value>logAdvisor</value>
<value>passwordAdvisor</value>
</list>
</property>
</bean>
</beans>
利用Spring提供的一个RegexMethodPointcutAdvisor可以非常容易地指定要截获的方法。运行结果如下,可以看到返回结果变为"******":
还需要继续增强ServiceBean?我们编写一个ExceptionAdvisor,在业务方法抛出异常时能做一些处理:
/**
* Copyright_2006, Liao Xuefeng
* Created on 2006-3-9
*/
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工程
相关推荐
《JavaWeb整合开发完全自学手册》介绍如何整合Struts+Hibernate+Spring+Eclipse进行J2EE开发,所有实例都基于MyEclipseIDE开发,引领读者快速进入基于JavaWeb的J2EE应用领域。《JavaWeb整合开发完全自学手册》主要...
此外,了解Spring框架整合MyBatis及Spring MVC的细节,对于开发基于Java EE的企业级应用非常关键。Spring MVC负责Web层的请求处理,MyBatis则是持久层框架,能够简化数据库操作。熟练掌握这些框架的整合使用,能够...
SSM(spring+spring MVC+mybatis)开发学生信息后台管理系统,实现学生增删改查功能设计一个简单的学生信息管理系统,要求使用SSM框架技术整合实现,用户登录后能够通过Web页面添加、删除、修改和查询学生信息 ...
SSM(Spring+SpringMVC+MyBatis)是Java Web开发中的经典组合,尤其在企业级应用中广泛使用。这个商品管理系统就是基于SSM框架搭建的,它利用Eclipse作为开发工具,实现了基础的商品管理功能,包括增删改查操作。...
轻量级 J2EE 企业应用实战:Struts+Spring+Hibernate 整合开发。 一本很好的J2EE开发的入门和提高书籍。包含书和代码。但是太大,而CSDN最大限制10M,所以共有12个包。前三个是书,后9个是code。
开发工具:ECLIPSE + TOMCAT + MYSQL + NAVICAT 使用技术:JAVA, SPRING, MYBA 项目描述:该项目为一个博客系统,具有文章的发布修改功能,修改文章分类,添加新的用户,发表评论。
轻量级 J2EE 企业应用实战:Struts+Spring+Hibernate 整合开发。 一本很好的J2EE开发的入门和提高书籍。包含书和代码。但是太大,而CSDN最大限制10M,所以共有13个包。前三个是书,后10个是code。
轻量级 J2EE 企业应用实战:Struts+Spring+Hibernate 整合开发。 一本很好的J2EE开发的入门和提高书籍。包含书和代码。但是太大,而CSDN最大限制10M,所以共有12个包。书3部分和代码9部分。
6. **Eclipse IDE**:Eclipse是一个强大的集成开发环境,支持多种编程语言,尤其是Java。在开发这个项目时,Eclipse提供了代码编辑、调试、版本控制、构建工具集成等功能,提高了开发效率。 关于压缩包中的文件目录...
轻量级 J2EE 企业应用实战:Struts+Spring+Hibernate 整合开发。 一本很好的J2EE开发的入门和提高书籍。包含书和代码。但是太大,而CSDN最大限制10M,所以共有13个包。前三个是书,后10个是code。
使用环境:MyEclipse/Eclipse + Tomcat + MySQL。 使用技术:Spring MVC + Spring + MyBatis / JSP + Servlet + JavaBean + JDBC。
使用环境:MyEclipse/Eclipse + Tomcat + MySQL。 使用技术:Spring MVC + Spring + MyBatis / JSP + Servlet + JavaBean + JDBC。
使用环境:MyEclipse/Eclipse + Tomcat + MySQL。 使用技术:Spring MVC + Spring + MyBatis 或 JSP + Servlet + JavaBean + JDBC。 演示地址:https://ymjin.blog.csdn.net/article/details/120991940
开发环境:Eclipse ,JDK 1.8 ,Tomcat7 技术选型: 后端技术 核心框架:Spring Framework 4.3.5 视图框架:Spring MVC 4.3.5 任务调度:Spring + Quartz 2.2.3 持久层框架:MyBatis 3.4.2 + Mybatis-plus 2.0.1 ...
由于文件太大上传不方便,你们下载也不方便而且昂贵,所以大家放心下载,通过发给我邮件,我会将高清晰的pdf格式文件发给大家 这本书很经典 作者李刚 分别讲解 jsp struts spring hibernate 并通过实例进行整合开发 ...
Bootstrap运行环境jdk8 + tomcat8 + mysql + Eclipse + maven项目技术:spring + spring mvc + mybatis + bootstrap + jquery前人植入树后人乘凉,最开始系统是IDEA开发,目前该版本修改为eclipse版本,增加和删除了...
《疯狂Ajax讲义:Prototype/jQuery+DWR+Spring+Hibernate整合开发》是《基于J2EE的Ajax宝典》的第二版。《基于J2EE的Ajax宝典》面市近2年,作为Ajax领域最全面、实用的图书,一直深受读者的好评。全书主要分为三个...
开发环境:Eclipse ,JDK 1.8 ,Tomcat7 技术选型: 后端技术 核心框架:Spring Framework 4.3.5 视图框架:Spring MVC 4.3.5 任务调度:Spring + Quartz 2.2.3 持久层框架:MyBatis 3.4.2 + Mybatis-plus 2.0.1 ...
这个压缩包文件“struts+spring+hibernate开发的+开发环境_eclipse3.1+MyEclipse4.1+tomcat5”显然提供了一个基于这些技术的新闻发布系统的开发环境。下面我们将详细探讨这三大框架以及相关的开发工具和服务器。 **...
该项目是一个经典的Java Web开发组合,使用了Maven作为构建工具,Struts2作为表现层框架,Hibernate3作为持久层框架,Spring3作为依赖注入和事务管理框架,且基于Eclipse IDE进行开发。以下是对这些技术栈的详细说明...