??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲人xxx日本人18,亚洲线精品一区二区三区,亚洲夜夜欢A∨一区二区三区http://www.tkk7.com/franlk/category/10336.htmlzh-cnFri, 02 Mar 2007 02:55:33 GMTFri, 02 Mar 2007 02:55:33 GMT60[摘录]Spring入门http://www.tkk7.com/franlk/articles/42283.htmlFRANLK 的个人空?/dc:creator>FRANLK 的个人空?/author>Fri, 21 Apr 2006 02:41:00 GMThttp://www.tkk7.com/franlk/articles/42283.htmlhttp://www.tkk7.com/franlk/comments/42283.htmlhttp://www.tkk7.com/franlk/articles/42283.html#Feedback0http://www.tkk7.com/franlk/comments/commentRss/42283.htmlhttp://www.tkk7.com/franlk/services/trackbacks/42283.htmlhttp://www.codechina.net/resource/html/2006-04/07/150546.html
Spring入门

Spring是一个非怼U的轻量框架Q通过Spring的IoC容器Q我们的x点便攑ֈ了需要实现的业务逻辑上。对AOP的支持则能让我们动态增Z务方法。编写普通的业务逻辑Bean是非常容易而且易于试的,因ؓ它能qJ2EE容器Q如ServletQJSP环境Q单独进行单元测试。最后的一步便是在Spring框架中将q些业务Bean以XML配置文g的方式组lv来,它们按照我们预定的目标正常工作了!非常ҎQ?/p>

本文给Z个基本的Spring入门CZQƈ演示如何使用Spring的AOP复杂的业务逻辑分离到每个方面中?/p>

1Q开发环境配|?br />2Q编写Bean接口及其实现
3Q在Spring中配|Beanq获得Bean的实?br />4Q编写Advisor以增强ServiceBean
5Qȝ

1Q开发环境配|?/h3>

首先Q需要正配|Java环境。推荐安装JDK1.4.2Qƈ正确配置环境变量Q?/p>

JAVA_HOME=<JDK安装目录>
CLASSPATH=.
Path=%JAVA_HOME%\\bin;…?/p>

我们用免费的Eclipse 3.1作ؓIDE。新Z个Java ProjectQ将Spring的发布包spring.jar以及commons-logging-1.0.4.jar复制到Project目录下,q在Project > Properties中配|好Java Build PathQ?/p>

src=uppic/20060407/1405270.jpg

2Q编写Bean接口及其实现

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

/**
 * 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);
    }
}

Z化逻辑Q我们用一个Map保存用户名和口o?/p>

现在Q我们已l有了一个业务Bean。要试它非常容易,因ؓ到目前ؓ止,我们q没有涉及到Spring容器Q也没有涉及CQ何Web容器Q假定这是一个Web应用E序关于用户理的业务BeanQ。完全可以直接进行Unit试Q或者,单地写个mainҎ试Q?/p>

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

执行l果Q?br />src=uppic/20060407/1405271.jpg

3Q在Spring中配|Beanq获得Bean的实?/h3>

我们已经在一个mainҎ中实C业务Q不q,对象的生命周期交给容器理是更好的办法Q我们就不必为初始化对象和销毁对象进行硬~码Q从而获得更大的灉|性和可测试性?/p>

惌把ServiceBean交给Spring来管理,我们需要一个XML配置文g。新Z个beans.xmlQ放到src目录下,保在classpath中能扑ֈ此配|文Ӟ输入以下内容Q?/p>

<?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的BeanQ默认地QSpring为每个声明的Bean仅创Z个实例,q过id来引用这个Bean。下面,我们修改mainҎQ让Spring来管理业务BeanQ?/p>

/**
 * 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();
    }
}

执行l果Q?br /> src=uppic/20060407/1405272.jpg

׃我们要通过mainҎ启动Spring环境Q因此,首先需要初始化一个BeanFactory。红色部分是初始化Spring的BeanFactory的典型代码,只需要保证beans.xml文g位于classpath中?/p>

然后Q在BeanFactory中通过id查找Q即可获得相应的Bean的实例,q将光当转型为合适的接口?/p>

接着Q实Cpd业务操作Q在应用E序l束前,让Spring销毁所有的Bean实例?/p>

Ҏ上一个版本的MainQ可以看出,最大的变化是不需要自q理Bean的生命周期。另一个好处是在不更改实现cȝ前提下,动态地为应用程序增加功能?/p>

4Q编写Advisor以增强ServiceBean

所谓AOPx分散在各个Ҏ处的公共代码提取C处,q过cM拦截器的机制实现代码的动态织入。可以简单地惌成,在某个方法的调用前、返回前、调用后和抛出异常时Q动态插入自q代码。在弄清楚Pointcut、Advice之类的术语前Q不如编写一个最单的AOP应用来体验一下?/p>

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

/**
 * 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() + "()");
    }
}

然后Q修改beans.xmlQ?/p>

<?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>

注意观察修改后的配置文gQ我们用了一个ProxyFactoryBean作ؓservice来与客户端打交道Q而真正的业务Bean即MyServiceBean被声明ؓserviceTargetq作为参数对象传递给ProxyFactoryBeanQproxyInterfaces指定了返回的接口cd。对于客L而言Q将感觉不出M变化Q但却动态加入了LogAdvisorQ关pd下:
 src=uppic/20060407/1405273.jpg

q行l果如下Q可以很Ҏ看到调用了哪些方法:
 src=uppic/20060407/1405274.jpg

要截h定的某些Ҏ也是可以的。下面的例子修改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();
    }
}

q个PasswordAdvisor截获ServiceBean的getPassword()Ҏ的返回|q将其改?**。l修改beans.xmlQ?/p>

<?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可以非常Ҏ地指定要截获的方法。运行结果如下,可以看到q回l果变ؓ******Q?br /> src=uppic/20060407/1405275.jpg

q需要l增强ServiceBeanQ我们编写一个ExceptionAdvisorQ在业务Ҏ抛出异常时能做一些处理:

/**
 * 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());
    }
}

此Adviced到beans.xml中,然后在业务Bean中删除一个不存在的用P故意抛出异常Q?/p>

service.deleteUser("not-exist");

再次q行Q注意到ExceptionAdvisor记录下了异常Q?br /> src=uppic/20060407/1405276.jpg

5Qȝ

利用Spring非常强大的IoC容器和AOP功能Q我们能实现非常灉|的应用,让Spring容器理业务对象的生命周期,利用AOP增强功能Q却不媄响业务接口,从而避免更改客L代码?/p>

Z实现q一目标Q必dl牢讎ͼ面向接口~程。而Spring默认的AOP代理也是通过Java的代理接口实现的。虽然Spring也可以用CGLIB实现Ҏ通类的代理,但是Q业务对象只要没有接口,׃变得难以扩展、维护和试?/p>



]]>
[摘录]Learn Spring in spring(? http://www.tkk7.com/franlk/articles/42279.htmlFRANLK 的个人空?/dc:creator>FRANLK 的个人空?/author>Fri, 21 Apr 2006 02:35:00 GMThttp://www.tkk7.com/franlk/articles/42279.htmlhttp://www.tkk7.com/franlk/comments/42279.htmlhttp://www.tkk7.com/franlk/articles/42279.html#Feedback0http://www.tkk7.com/franlk/comments/commentRss/42279.htmlhttp://www.tkk7.com/franlk/services/trackbacks/42279.htmlhttp://www.codechina.net/resource/html/2005-04/10/16122.html
Learn Spring in spring(?
四、Spring中的事务控制

Bromon原创 请尊重版?br />
  Spring和EJB一P提供了两U事务管理方式:~程式和声明式。在考试pȝ中我们将使用声明式的事务理Q这是spring推荐的做法。用这U方式可以体验到spring的强大便P而且我们无须在DaocM~写MҎ的代码,只需要通过配置文g可以让普通的javacd载到事务理中,q个意义是很重大的?br />
  Spring中进行事务管理的通常方式是利用AOPQ面向切片编E)的方式,为普通javacd装事务控Ӟ它是通过动态代理实现的Q由于接口是延迟实例化的Qspring在这D|间内通过拦截器,加蝲事务切片。原理就是这P具体l节请参考jdk中有兛_态代理的文档。本文主要讲解如何在spring中进行事务控制?br />
  动态代理的一个重要特征是Q它是针Ҏ口的Q所以我们的dao要通过动态代理来让spring接管事务Q就必须在dao前面抽象Z个接口,当然如果没有q样的接口,那么spring会用CGLIB来解决问题,但这不是spring推荐的方式,我们也不做讨论?br />
  参照前面的例子,我们为StudentManager.java定义一个接口,它的内容如下Q?br />
  1. /*
  2.  * 创徏日期 2005-3-25
  3.  */
  4. package org.bromon.spring.examer.student;
  5. import java.util.List;
  6. import org.bromon.spring.examer.pojo.Student;
  7. /**
  8.  * @author Bromon
  9.  */
  10. public interface StudentManagerInterface
  11. {
  12.     public void add(Student s);
  13.     public void del(Student s);
  14.     public void update(Student s);
  15.     
  16.     public List loadAll();
  17.     public Student loadById(int id);
  18. }


  StudentManager也应该做Z改,实现该接口:

  1. public class StudentManager extends HibernateDaoSupport implements StudentManagerInterface

  现在需要修攚w|文Ӟ用于定义Hibrenate适用的事务管理器Qƈ且把sessionFactory注入q去Q同时还需要通过注册一个DefaultTransactionAttribute对象Q来指出事务{略。其中sessionFactory的定义已l在本文的第三章中说明?br />
  首先定义一个Hibernate的事务管理器Q让它来理sessionFactoryQ?br />
  1. <bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
  2.  <property name="sessionFactory">
  3.   <ref bean="sessionFactory"/>
  4.  </property>
  5. </bean>


  下面定义事务理{略Q我们希望把{略定义在方法这个别上Q提供最大的灉|性,本例中将addҎ定义为:PROPAGATION_REQUIRES_NEWQ这可以保证它将始终q行在一个事务中?br />
  1. <bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
  2.  <property name="properties">
  3.   <props>
  4.    <prop key="add">
  5.     PROPAGATION_REQUIRES_NEW
  6.    </prop>
  7.   </props>
  8.  </property>
  9. </bean>


  我们不仅可以为addҎ定义事务{略,q可以定义事务隔ȝ度和回滚{略,他们以逗号隔开,比如我们的add事务可以定义?

  1. <prop key="add">
  2.     PROPAGATION_REQUIRES_NEW,-ExamerException
  3. </prop>


  q个事务{略表示addҎ会独占一个事务,当事务过E中产生ExamerException异常Q事务会回滚?br />
  Add/update/del都是写入ҎQ对于selectQ读取)ҎQ我们可以指定较为复杂的事务{略Q比如对于loadAll()ҎQ?br />
 
  1. <prop key=”loadAll?gt;
  2.   PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITED,readOnly
  3.  </prop>


  该事务的含义为,loadAllҎ支持事务Q不会读取未提交的数据,它的数据为只读(可提高执行速度Q?br />
  如你所见,我们的StudentManagerInterface接口中还有一个loadById(int id)ҎQ也许我们将来还会有很多的loadByXXXX的方法,N要一一Z们指定事务策略?太烦ZQ他们应该和loadAll()一P所以我们可以用通配W,定义所有的loadXXXXҎQ?br />
    
  1. <prop key=”load*?gt;
  2.         PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITED,readOnly
  3.     </prop>


 现在可以定义事务理器:
  1. <bean id="studentManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
  2.  <property name="target">
  3.   <ref bean="studentManager"/>
  4.  </property>
  5.  <property name="transactionManager">
  6.   <ref bean="transactionManager"/>
  7.  </property>
  8.  <property name="transactionAttributeSource">
  9.   <ref bean="transactionAttributeSource"/>
  10.  </property>
  11. </bean>

  q个bean的外观是一个接?StudentManagerInterface)Q我们指Z它的具体实现(studentManager)Q而且为它l定了事务策略。在客户端用的时候,获得对象是StudentManagerInterfaceQ所有的操作都是针对q个接口的。测试代码ƈ没有改变Q我们虽然修改了很多地方Q加入了事务控制Q但是客Lq没有受到媄响,q也体现了spring的一些优ѝ测试代码如下:

  
  1. public void testAdd() 
  2.     {
  3.         ApplicationContext ctx=new ClassPathXmlApplicationContext("springConfig.xml");
  4.         StudentManager sm=(StudentManager)ctx.getBean("studentManager");
  5.         
  6.         Student s=new Student();
  7.         s.setId(1);
  8.         s.setName("bromon");
  9.         s.setPassword("123");
  10.         s.setGrade(1);
  11.         s.setSex(0);
  12.         
  13.         sm.add(s);
  14. }

  通过以上的代码可以看出,spring可以单的把普通的java classU_事务理Q声明性的事务操作h也很Ҏ。有了spring之后Q声明性事务不再是EJB独有Q我们不必ؓ了获得声明性事务的功能而去忍受EJB带来的种U不ѝ?br />
  我所使用的mysql是不支持事务的,你可以更换用PostgreSQLQ有了spring+hibernateQ更换dbq不像以前那h怖了Q步骤很单:

1、    添加PostgreSQL的jdbc驱动
2、    修改dataSource配置Q包括驱动名U、url、帐受密?br />3、    修改sessionFactory的数据库dailet为net.sf.hibernate.dialect.PostgreSQLDialect
4、    修改hbm.xml中的主键生成{略为increment

所有的修改都在配置文g中完成,业务代码不需要Q何修改,我很满意QHow about u?

附A  pring中的所有事务策?br />
    PROPAGATION_MANDATORY
    PROPAGATION_NESTED            
    PROPAGATION_NEVER            
    PROPAGATION_NOT_SUPPORTED
    PROPAGATION_REQUIRED
    PROPAGATION_REQUIRED_NEW
    PROPAGATION_SUPPORTS

附B  Spring中所有的隔离{略Q?br />
    ISOLATION_DEFAULT
    ISOLATION_READ_UNCOMMITED
    ISOLATION_COMMITED
    ISOLATION_REPEATABLE_READ
    ISOLATION_SERIALIZABLE


]]>
[摘录]Learn Spring in spring(? http://www.tkk7.com/franlk/articles/42278.htmlFRANLK 的个人空?/dc:creator>FRANLK 的个人空?/author>Fri, 21 Apr 2006 02:34:00 GMThttp://www.tkk7.com/franlk/articles/42278.htmlhttp://www.tkk7.com/franlk/comments/42278.htmlhttp://www.tkk7.com/franlk/articles/42278.html#Feedback0http://www.tkk7.com/franlk/comments/commentRss/42278.htmlhttp://www.tkk7.com/franlk/services/trackbacks/42278.htmlhttp://www.codechina.net/resource/html/2005-04/10/16123.html
Learn Spring in spring(?
三、spring中的hibernate开?br />
Bromon原创 请尊重版?br />
  spring中对hibernate的支持是非常强大的,从一个简单的例子q得出来,从这个例子中我们q将Ҏ谓的轻量U容器做一些讨论?br />
  首先需要配|数据源Q通常我们有两U方式获得ConnectionQ一是自q写代码获得连接,二是从JNDI环境中得到DataSourceQ然后生一个Connection。无论怎样Q既然是spring下面的对象,应该注册到配置文g中。假设我们需要一个连接mysql下面一个叫做examer的数据库Q手动方式的配置是:

  1. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  2.   <property name="driverClassName">
  3.     <value>com.mysql.jdbc.Driver</value>
  4.   </property>
  5.   <property name="url">
  6.     <value>jdbc:mysql://localhost/examer</value>
  7.   </property>
  8.   <property name="username">
  9.     <value>root</value>
  10.   </property>
  11.   <property name="password">
  12.     <value></value>
  13.   </property>
  14. </bean>


  很好L不是Q假如我们用JNDI数据源,那么dataSource的声明就应该是:

  1. <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
  2.   <property name="jndiName">
  3.     <value>java:compenvjdbcspringExamer</value>
  4.   </property>
  5. </bean>

  你需要在JNDI环境中绑定一个名为jdbc/springExamer的东西,q段代码才有实际意义。另外需要提醒的是,所有的bean声明Q它的id必须是唯一的?br />
  在本pȝ中,数据库操作是被hibernate装h的,所以dataSource是不需要注入到具体的逻辑cMQ它只会被注lhibernate的sessionFactory?br />
  按照常规思\Q我们需要在spring中注册hibernate的sessionFactoryQ它应该是我们自q写的一个类Q获得dataSourceQ返回sessionFactoryQ其他的逻辑c通过q个sessionFactory获得sessionq行数据库操作?br />
  但是我们有另外一U选择Qspring直接提供了对sessionFactory的封装,你只需要注册一个spring自己的类Q给它提供必ȝ属性,它会q回一个org.springframework.orm.hibernate.HibernateTemplateQ这个类装了add、del{操作,它的装E度相当高,通过它来~写hibernate应用非常单。但是问题出来了Q我们该如何选择Q?br />
  表面上看Q用spring自己的库无疑更加单,但是h意,spring是一个轻量的框Ӟ所谓轻量Q一个重要特征就是无侵入性,也就是你使用q套框架Q不会被它绑定,被spring理的类Q应该不需要用它的接口和抽象c,q样你的pȝ不会对spring产生依赖。但是如果你使用了spring装的方式去操作hibernateQ就必须l承org.springframework.orm.hibernate.support.HibernateDaoSupportc,q导致了l定。所以做q样的选择是有点痛苦的Q如果有一天spring框架不存在了Q你的代码怎么升l护Q具体问题只能具体分析,在我们的应用中,完全使用了spring装的HibernateTemplateQ它太好用了Q所以容易上瘾?br />
  假设我们有一张student表,l构很简单:

  
  1. id      自动增长
  2.   name     varchar(40)
  3.   password   varchar(32)
  4.   grade        int(4)      q
  5.   sex     Boolean      性别(true为男Qfalse为女)

  设计一个StudentcL映射q张表:

  1. /*
  2.  * 创徏日期 2005-3-17
  3.  */
  4. package net.bromon.spring.examer.pojo;
  5. /**
  6.  * @author Bromon
  7.  */
  8. public class Student 
  9. {
  10.     private int id;
  11.     private String name;
  12.     private String password;
  13.     private int grade;//q
  14.     private boolean sex;
  15.     
  16.     getsetҎ……?
  17. }

  ~写Student.hbm.xmlQ让hibernate知道如何d联student表和Studentc,该文件和Student.java在同一目录Q?br />
  1. <hibernate-mapping>
  2.   <class name="net.bromon.spring.examer.pojo.Student" table="student">
  3.     <id name="id" column="id">
  4.       <generator class="identity"/>
  5.     </id>
  6.         
  7.     <property name="name" column="name" />
  8.     <property name="password" column="password" />
  9.     <property name="grade" column="grade" />
  10.     <property name="sex" column="sex" />
  11.   </class>
  12. </hibernate-mapping>

  然后我们可以在spring中配|sessionFactoryQ?br />
  1. <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
  2.   <property name="dataSource">
  3.     <ref bean="dataSource"/>
  4.   </property>
  5.         
  6.   <property name="hibernateProperties">
  7.     <props>
  8.       <prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect</prop>
  9.     </props>
  10.   </property>
  11.         
  12.   <property name="mappingDirectoryLocations">
  13.     <list>
  14.       <value>classpath:/netbromonspringexamerpojo</value>
  15.     </list>
  16.   </property>
  17. </bean>

  其中引用了我们之前注册过的dataSourceQmappingDirectoryLocations属性指明了.hbm.xml文g在哪里\径,该文件夹下面?hbm.xml文g会被全部加蝲?br />
  一切都准备qAQ现在我们要加入一个StudentManagerc,来进行增删查改的操作Q?br />
  1. /*
  2.  * 创徏日期 2005-3-17
  3.  */
  4. package net.bromon.spring.examer.student;
  5. import net.bromon.spring.examer.pojo.Student;
  6. import org.springframework.orm.hibernate.HibernateTemplate;
  7. import org.springframework.orm.hibernate.LocalSessionFactoryBean;
  8. import org.springframework.orm.hibernate.support.HibernateDaoSupport;
  9. /**
  10.  * @author Bromon
  11.  */
  12. public class StudentManager extends HibernateDaoSupport
  13. {
  14.     private LocalSessionFactoryBean sessionFactory;
  15.     private HibernateTemplate ht;
  16.     public StudentManager()
  17.     {
  18.         this.ht=super.getHibernateTemplate();
  19.     }
  20.     
  21.     public void add(Student s)
  22.     {   
  23.         ht.save(s);//插入一条数据只需要这一行代?/font>
  24.     }
  25. }

  该类只演CZ如何增加一个StudentQHibernateTemplateq封装了很多有用的方法,h阅spring文档。StudentManager中的sessionFactory是由spring注入的,但是StudentManagerq没有对sessionFactory做Q何的处理Q这是因为所有的处理都被HibernateDaoSupport.getHibernateTemplate()装。整个StudentManager中也看不CQ何的异常处理Q他们也都被基类装了?br />
  最后一个步骤就是在spring中注册StudentMangerQ然后向它注入sessionFactoryQ?br />
  1. <bean id="studentManager" class="net.bromon.spring.examer.student.StudentManager">
  2.   <property name="sessionFactory">
  3.     <ref bean="sessionFactory"/>
  4.   </property>
  5. </bean>


  所有的配置都完成了Q下面做单元试Q?br />
  1. /*
  2.  * 创徏日期 2005-3-17
  3.  */
  4. package net.bromon.spring.examer.student.test;
  5. import java.io.FileInputStream;
  6. import org.springframework.beans.factory.xml.XmlBeanFactory;
  7. import org.springframework.context.ApplicationContext;
  8. import org.springframework.context.support.ClassPathXmlApplicationContext;
  9. import net.bromon.spring.examer.pojo.Student;
  10. import net.bromon.spring.examer.student.StudentManager;
  11. import junit.framework.TestCase;
  12. /**
  13.  * @author Bromon
  14.  */
  15. public class TestStudentManager extends TestCase {
  16.     public void testAdd() 
  17.     {
  18.         try
  19.         {
  20.             ApplicationContext context =new ClassPathXmlApplicationContext("springConfig.xml");
  21.             
  22.             Student s=new Student();
  23.             s.setName("bromon");
  24.             s.setPassword("123");
  25.             s.setGrade(3);
  26.             s.setSex(true);
  27.             
  28.             ((StudentManager)context.getBean("studentManager")).add(s);
  29.         }catch(Exception e)
  30.         {
  31.             e.printStackTrace();
  32.         }
  33.     }
  34. }

  Spring已经hibernate的操作简化到了非帔R的程度,最关键的是整个开发可以由设计来驱动,如果一个团队对spring有够的熟悉Q那么完全可以由设计师规划所有的c,整理清楚cM间的关系Q写成配|文Ӟ然后~写hibernate映射文gQ将数据表与pojo兌Q成员就可以完全在设计方案内工作Q利用spring装好的hibernate模版Q开发v来速度非常快,调试也很Ҏ。它能够解决如何在团队内贯彻设计Ҏ的问题?br />
  ׃本文不讲解hibernate的用,所以相兛_容请查阅hibernate文档?br />
下一:spring中的事务控制


]]>
[摘录]Learn Spring in spring(?http://www.tkk7.com/franlk/articles/42277.htmlFRANLK 的个人空?/dc:creator>FRANLK 的个人空?/author>Fri, 21 Apr 2006 02:33:00 GMThttp://www.tkk7.com/franlk/articles/42277.htmlhttp://www.tkk7.com/franlk/comments/42277.htmlhttp://www.tkk7.com/franlk/articles/42277.html#Feedback0http://www.tkk7.com/franlk/comments/commentRss/42277.htmlhttp://www.tkk7.com/franlk/services/trackbacks/42277.htmlhttp://www.codechina.net/resource/html/2005-04/10/16124.html
Learn Spring in spring(?
二、spring理对象的简单例?br />
Bromon原创 请尊重版?br />
  M需要交lspring理的对象,都必d配置文g中注册,q个q程被称为wiringQ下面做一个最单的Hello world演示Q我们将要注册的cd下:

  1. /*
  2.  * 创徏日期 2005-3-22
  3.  */
  4. package org.bromon.spring.test;
  5. /**
  6.  * @author Bromon
  7.  */
  8. public class HelloTalker 
  9. {
  10.     public String greeting()
  11.     {
  12.         return "hello world";
  13.     }
  14. }

  然后我们来编写一个spring配置文gQ文件名LQ在我这里它是springConfig.xmlQ需要注意的是这个文件应该存攑֜classpath所包含的\径中Q?br />
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
  3. <beans>
  4.  <bean id=”helloTalker”?b>class=” org.bromon.spring.test.HelloTalker?gt;
  5.  </bean>
  6. </beans>

  通过使用bean标签Q注册了一个HelloTalker对象Q它的名字叫做helloTalker。然后我们编写一个测试类Q它的工作是利用spring框架提供的接口,加蝲配置文gQ通过指定对象的idQ获得一个对象。它的代码如下:
  1. /*
  2.  * 创徏日期 2005-3-17
  3.  */
  4. package org.bromon.spring.test.junit;
  5. import java.io.FileInputStream;
  6. import org.springframework.beans.factory.xml.XmlBeanFactory;
  7. import org.springframework.context.ApplicationContext;
  8. import org.springframework.context.support.ClassPathXmlApplicationContext;
  9. import org.bromon.spring.test;
  10. /**
  11.  * @author Bromon
  12.  */
  13. public class TestStudentManager extends TestCase {
  14.     public void testHelloTalker() 
  15.     {
  16.         try
  17.         {
  18.             ApplicationContext context =new ClassPathXmlApplicationContext("springConfig.xml");
  19.             
  20. HelloTalker ht=(HelloTalker)context.getBean(“helloTalker?;
  21. System.out.println(ht.greeting());
  22.         }catch(Exception e)
  23.         {
  24.             e.printStackTrace();
  25.         }
  26.     }
  27. }

  q个E序完成了Q因为只有一个对象HelloTalker被注册到了spring中,所以不存在对象间的依赖Q当然也׃涉及依赖注入。下面演CZ个简单的依赖注入Q?br />
  W一步是修改HelloTalkerQ增加一个String name属性:
  1. public String name;


  属性编写setҎQ该Ҏ必须严格遵守javabean的命名规则:
  1. public void setName(String name)
  2. {
  3.   this.name=name;
  4. }

  修改greetingҎQ?br />
  1. public String greeting()
  2. {
  3.   return "hello "+name;
  4. }

  如你所见,name属性没有初试化Q因为它的值将在运行过E中被spring动态注入?br />
  W二步,修改springConfig.xml中唯一的这个bean配置Q?br />
  1. <bean id=”helloTalker”?b>class=” org.bromon.spring.test.HelloTalker?gt;
  2.  <property name=”name?gt;
  3.   <value>bromon</value>
  4.  </property>
  5. </bean>


  修改完成。我们将一个名字”bromon”写dspringConfig.xml中,它会被动态的注入到HelloTalker的name属性中QgreetingҎ会把它打印出来。重新运行刚才的junitc,可以看到l果?br />
  我们只演CZ如何注入一个最单的StringQ实际上我们可以注入M值类型,也可以注入Q何类的实例,也可以注入List、Map、Properties。配|文件管理了所有的对象和对象间的关p,而对象则只负责执行自q功能Q他们的职责少Q藕合度低Q系l就容易测试,理l护也更Ҏ?br />
  <bean>标签q有很多属性,用于指定对象如何被实例化Q它也有很多子标{于配|对象的属性,请大家参考相关的DTD和文档,能够很快的掌握。本pd文章不是spring手册Qspring的基知识请参考spring in actionQ够详l准。后面的章节更多的讨论系l设计、开发的一些细节和高Ҏ?br />
下一:在spring中进行hibernate开?br />


]]>
[摘录]Learn Spring in spring(一)http://www.tkk7.com/franlk/articles/42276.htmlFRANLK 的个人空?/dc:creator>FRANLK 的个人空?/author>Fri, 21 Apr 2006 02:32:00 GMThttp://www.tkk7.com/franlk/articles/42276.htmlhttp://www.tkk7.com/franlk/comments/42276.htmlhttp://www.tkk7.com/franlk/articles/42276.html#Feedback0http://www.tkk7.com/franlk/comments/commentRss/42276.htmlhttp://www.tkk7.com/franlk/services/trackbacks/42276.htmlhttp://www.codechina.net/resource/html/2005-04/10/16126.html
Bromon原创 请尊重版?br />
  当前的Ş势是Q非常多的JavaE序员言必称SpringQ如此大面积的程序员集体叫”春”,体现了Spring框架的威力。春天正是叫春的好时候,你我一h叫春吧。^_^

  Spring的设计目的是化J2EE开发,所以如果我们学习、用它的时候还需要抓破头皮口吐白沫的话,岂不是个W话Q就我的l验来说QSpring在这斚w做得很好Q的是一个很牛叉易用的框架?br />
  之前我曾l设计过一个J2EE的考试pȝQ大量用了EJBQ详?a >http://blog.csdn.net/bromon/archive/2004/08/27/86291.aspxQ,我打同样用一个考试pȝ做例子,便于比较。两个系l的大致l构都差不多Q不q新的版本采用了轻量U的ҎQ用Hibernate作ؓORM框架Q所有的对象都交lspring来管理?br />
一、IoC与DI

  首先惌说IoCQInversion of ControlQ控制倒{Q。这是spring的核心,贯穿始终。所谓IoCQ对于spring框架来说Q就是由spring来负责控制对象的生命周期和对象间的关pR这是什么意思呢QD个简单的例子Q我们是如何扑֥朋友的?常见的情冉|Q我们到处去看哪里有长得漂亮w材又好的mmQ然后打听她们的兴趣爱好、qq受电话号、ip受iq号………,惛_法认识她们,投其所好送其所要,然后嘿嘿……这个过E是复杂深奥的,我们必须自己设计和面Ҏ个环节。传l的E序开发也是如此,在一个对象中Q如果要使用另外的对象,必d到它Q自己new一个,或者从JNDI中查询一个)Q用完之后q要对象销毁(比如Connection{)Q对象始l会和其他的接口或类藕合h?br />
  那么IoC是如何做的呢Q有点像通过婚介扑֥朋友Q在我和x友之间引入了一个第三者:婚姻介绍所。婚介管理了很多L奛_的资料,我可以向婚介提出一个列表,告诉它我x个什么样的女朋友Q比如长得像李嘉ƣ,w材像林熙雷Q唱歌像周杰伦,速度像卡z斯Q技术像齐达内之cȝQ然后婚介就会按照我们的要求Q提供一个mmQ我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介l我们的人选不W合要求Q我们就会抛出异常。整个过E不再由我自己控Ӟ而是有婚介这样一个类似容器的机构来控制。Spring所倡导的开发方式就是如此,所有的c都会在spring容器中登讎ͼ告诉spring你是个什么东西,你需要什么东西,然后spring会在pȝq行到适当的时候,把你要的东西dl你Q同时也把你交给其他需要你的东ѝ所有的cȝ创徏、销毁都由spring来控Ӟ也就是说控制对象生存周期的不再是引用它的对象Q而是spring。对于某个具体的对象而言Q以前是它控制其他对象,现在是所有对象都被spring控制Q所以这叫控制反转。如果你q不明白的话Q我军_攑ּ?br />
  IoC的一个重Ҏ在系l运行中Q动态的向某个对象提供它所需要的其他对象。这一Ҏ通过DIQDependency InjectionQ依赖注入)来实现的。比如对象A需要操作数据库Q以前我们L要在A中自q写代码来获得一个Connection对象Q有了spring我们只需要告诉springQA中需要一个ConnectionQ至于这个Connection怎么构造,何时构造,A不需要知道。在pȝq行Ӟspring会在适当的时候制造一个ConnectionQ然后像打针一P注射到A当中Q这样就完成了对各个对象之间关系的控制。A需要依赖Connection才能正常q行Q而这个Connection是由spring注入到A中的Q依赖注入的名字p么来的。那么DI是如何实现的呢?Java 1.3之后一个重要特征是反射QreflectionQ,它允许程序在q行的时候动态的生成对象、执行对象的Ҏ、改变对象的属性,spring是通过反射来实现注入的。关于反的相关资料h阅java doc?br />
  理解了IoC和DI的概念后Q一切都变得简单明了,剩下的工作只是在spring的框架中堆积木而已?br />
下一:spring理对象的简单例?br />

]]>
[摘录]Jive论坛与Spring框架http://www.tkk7.com/franlk/articles/42275.htmlFRANLK 的个人空?/dc:creator>FRANLK 的个人空?/author>Fri, 21 Apr 2006 02:30:00 GMThttp://www.tkk7.com/franlk/articles/42275.htmlhttp://www.tkk7.com/franlk/comments/42275.htmlhttp://www.tkk7.com/franlk/articles/42275.html#Feedback0http://www.tkk7.com/franlk/comments/commentRss/42275.htmlhttp://www.tkk7.com/franlk/services/trackbacks/42275.html摘录地址Q?/font> http://www.codechina.net/resource/html/2006-04/07/150546.html
Jive论坛与Spring框架
  没有一U新技术是凭空诞生的,它的萌芽或胚胎L或多或少昄于以前的技术中QJive论坛是大家潜心研I的设计型应用程序,其相兌析可见本栏的GoF设计模式专栏?br />
  Jive和Spring同ؓ由JavaBeansl成的J2EE WebpȝQJive作ؓ早期成功设计案例Q其主要架构成ؓ大多数纯JavaBeanspȝ的流行架构,Spring也不例外?br />
  Spring框架除了是一UWeb层应用框Ӟq提供了讉KEJB层的接口Q也有JDBC/ORM的直接操作。Spring框架主要力是用IoC模式和AOP实现了Jivepȝ的通用功能Q从而得Jiveq样的纯JavaBeans架构设计可以重用在其它系l中?br />
  如果你感慨于Jive的设计理念,但是又苦于无法重用其设计ӞSpring框架已经帮你实现了?br />
  同时也要注意刎ͼSpring框架cM“杂烩”,它包含了很多J2EE应用的工Pcd对EJB的调用,它的MVC与Struts JSF也是相竞争的Q以UIoc和AOP设计来说QSpring框架也是一U很重的(Heavy、Weight)框架。Spring框架是复杂的Q如果想以Spring替代EJBQ那么无疑按了葫芦QL?br />
  Jive论坛和Spring框架联系hQ会帮助更多理解设计模式的程序员q速掌握最新的设计思潮Q而不是一U蟩跃式的强q接受。如果你对Jive有很好的研究Q将会发现Spring框架是Jive设计的更加通用的提升?br />
  在Jive?ForumFactory是整个系l的入口和突破点QJive通过ForumFactory整个系l掌控在一个工厂模式下Q这样做的好处是Q便于控制系l的JavaBeansQ例如,客户端通过ForumFactory可创Z个Forum或访问一个ForumQ但是是否有权限讉K呢?如下图:


  
   Jive通过ForumFactory这U访问引导到相应的ProxycdQ如ForumFactoryProxycȝQ通过代理模式对这些类q行权限控制讉K。这是代理模式的一个主要用处,但是研读Jive的代理模式会发现Q要为每个类实现一个Proxyc,非常琐碎Q有没有更优雅的方式呢? 当然使用动态代理?br />
  Spring框架基本是抽象上q设计,Spring框架Ҏ有JavaBeans的管理也是基于一个d口Bean Factory机制Q不同的是,BeanFactory可以 理所有应用的JavaBeansQ用者只要将自己的JavaBeans通过配置文g告诉BeanFactoryQ那么BeanFactory会加蝲q些JavaBeansQ例如:

  <beans>
    <bean id="exampleBean" class="eg.ExampleBean"/>
    <bean id="anotherExample" class="eg.ExampleBeanTwo"/>
  </beans>

  在Jive中,ForumFactory加蝲Jive自己的JavaBeans是通过工厂实现DbForumFactory实现的,如下代码QDbForumFactory引发了后Cpd功能实现Q这是纵向,而return new ForumFactoryProxyq个语句则类似引来一个切面,从一个横向方面实C权限讉K{功能:

private static String className = "com.jivesoftware.forum.database.DbForumFactory"; 

public static ForumFactory getInstance(Authorization authorization) { 
     //If no valid authorization passed in, return null. 
     if (authorization == null) { 
       return null; 
     } 
     //以下使用了Singleton 单态模式?br />     if (factory == null) { 
       synchronized(initLock) { 
         if (factory == null) { 
             ...... 

          try { 
               //动态{载类 
               Class c = Class.forName(className); 
               factory = (ForumFactory)c.newInstance(); 
           } 
           catch (Exception e) { 
               return null; 
           } 
         } 
       } 
     } 

     //Now, q回 proxy.用来限制授权对forum的访问?br />     return new ForumFactoryProxy(authorization, factory,                     factory.getPermissions(authorization)); 
   } 
 

  既然Spring框架也是通过一个Bean Factory加蝲所有的c,那么它是如何加蝲的?通过IoC模式Q也是依赖性注模式。在我以前文章“IoC模式”中Q我比较了Factory工厂模式创徏对象和Ioc模式的注对象实C间的异同QIoc相比工厂模式则更加解耦了调用者和被调用者之间关p,使用Ioc模式Q无需在调用者代码中涉及被调用者的具体实现?br />
  Spring框架不但可以向自己容器中注射应用者自己定义的JavaBeansQ也是创徏它们Q,而且也可以向q些JavaBeans通过setҎ实现数据赋倹{?br />
  一旦Bean Factoryq行时刻掌管q些Ȁzȝ对象QSpring通过AOP方式Q从一个横切面些JavaBeans提供了权限访问、事务锁{通用功能的实玎ͼq种实现是基于动态代理模式,而动态代理是AOP实现的一U方式?br />
  前面提到QJive中用代理模式实现权限访问,比代理模式更加简z和抽象的是动态代理,使用动态代理将使得调用者无需指定被调用者的代理c,q是动态代理区别代理模式的本质?br />
  动态代理这一优势Q又可以体现在另外一句话语上Q动态代理拦截了调用者对被调用者的调用Q正是这一功能W合了AOP的拦截器功能QؓAOP实现提供了可能?br />
  Spring框架使用了动态代理实现的AOPQ正是通过动态代理机制拦截了外界对Bean Factory理下的对象的调用。如下图Q?br />


 

  以上只是大体解构了Spring的架构,Spring框架在这个架构下Q还带了很多其它功能,如Web MVC、 DAO JDBC、 DAO ORM 、以及remoteQ后者类似我设计的EJBҎ调用框架?br />
  MQSpring实是Ioc和AOP的完应用,Ioc用来装蝲JavaBeansQ创些对象;AOP用来拦截q些对象的用,q才是框架设计的必然l典方式?br />


]]>
վ֩ģ壺 aëƬѹۿ| ޹Ʒһ| ձĻѿ| ߾ƷƵ| ˳Ƶ| ޹ƷëƬa| þþƷAVδʮ| ձһ| ޹ŮƷþþ| ƷƵ| պ˳վ| ޹91Ʒר| aëƬƵѿ| Ʒ޾Ʒպѷ| þþƷѲ| avƷҹɫҹ | ѿAVƬ| պŷƷ| Ʒþ޾þþþûʿ| xxxx߳Ƶ| ˾Ʒձר | Ʒվa | ȫAëƬѿվ| MM1313޹Ʒ| ޾þþþþ77777| Ļ߳ѿ| Ļ߹ۿձ | þþƷƷް | պ˳ۺ| ޳avƬ߹ۿ| wŷs| ɫʹۺһ| ҹ߹ۿ| ձh߾Ʒѹۿ| ۺɫ߾Ʒ| ˳˳ۺþþ | 91ƷѾþù鶹| ɫĻ߹ۿ| Ʒһ߹ۿ| è˳վ߹ۿ| ɫƨƨwwwӰԺѹۿƵ|