Spring入门

您所在的位置:网站首页 spring框架教程菜鸟idea Spring入门

Spring入门

2023-07-02 14:25| 来源: 网络整理| 查看: 265

Spring是一个非常优秀的轻量级框架,通过Spring的IoC容器,我们的关注点便放到了需要实现的业务逻辑上。对AOP的支持则能让我们动态增强业务方法。编写普通的业务逻辑Bean是非常容易而且易于测试的,因为它能脱离J2EE容器(如Servlet,JSP环境)单独进行单元测试。最后的一步便是在Spring框架中将这些业务Bean以XML配置文件的方式组织起来,它们就按照我们预定的目标正常工作了!非常容易!

本文将给出一个基本的Spring入门示例,并演示如何使用Spring的AOP将复杂的业务逻辑分离到每个方面中。

开发环境配置

首先,需要正确配置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:

编写Bean接口及其实现

我们实现一个管理用户的业务Bean。首先定义一个ServiceBean接口,声明一些业务方法:

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中实现接口:

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方法测试:

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"); } } }

执行结果:

在Spring中配置Bean并获得Bean的实例

我们已经在一个main方法中实现了业务,不过,将对象的生命周期交给容器管理是更好的办法,我们就不必为初始化对象和销毁对象进行硬编码,从而获得更大的灵活性和可测试性。

想要把ServiceBean交给Spring来管理,我们需要一个XML配置文件。新建一个beans.xml,放到src目录下,确保在classpath中能找到此配置文件,输入以下内容:

以上XML声明了一个id为service的Bean,默认地,Spring为每个声明的Bean仅创建一个实例,并通过id来引用这个Bean。下面,我们修改main方法,让Spring来管理业务Bean:

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的生命周期。另一个好处是在不更改实现类的前提下,动态地为应用程序增加功能。

编写Advisor以增强ServiceBean

所谓AOP即是将分散在各个方法处的公共代码提取到一处,并通过类似拦截器的机制实现代码的动态织入。可以简单地想象成,在某个方法的调用前、返回前、调用后和抛出异常时,动态插入自己的代码。在弄清楚Pointcut、Advice之类的术语前,不如编写一个最简单的AOP应用来体验一下。

考虑一下通常的Web应用程序都会有日志记录,我们来编写一个LogAdvisor,对每个业务方法调用前都作一个记录:

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:

com.crackj2ee.example.spring.ServiceBean logAdvisor

注意观察修改后的配置文件,我们使用了一个ProxyFactoryBean作为service来与客户端打交道,而真正的业务Bean即MyServiceBean被声明为serviceTarget并作为参数对象传递给ProxyFactoryBean,proxyInterfaces指定了返回的接口类型。对于客户端而言,将感觉不出任何变化,但却动态加入了LogAdvisor,关系如下:

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

要截获指定的某些方法也是可以的。下面的例子将修改getPassword()方法的返回值:

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


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3