在加拿大
预留
评论
回复: JAVA/J2EE, Struts, Spring, Hibernate学习笔记转贴 spring学习http://hi.baidu.com/ayongs/blog/item/b971923d9d0d0905bba167e9.html学习spring的过程,发现主要掌握3个概念,之后再根据实例做一个小程序,就基本入门了。 三个概念分别为AOP,IoC,和DI。 1、IoC(Inversion of control )反转控制 先看IoC的概念。IoC,Inversion of Control,控制反转[1], 其原理是基于OO设计 原则的The Hollywood Principle:Don't call us, we'll call you。 也就是说,所有的组件[2]都 是被动的(Passive), 所有的组件初始化和调用都由容器负责。组件处在一个容器当中,由容器负责管理。 然看举个例子看看IoC在Spring框架里是怎么实现的。所谓IoC就是一个用XML来定义生成对象的模式,我们看看如果来使用的。 要说明IoC模 式最好的方法是使用代码。下边是一段正常的代码。 class ClassA... public String aMethod(String arg){ String result = instanceOfClassB.bMethod(); do something; return result; } 在上边的代码里,我们要解决的问题是:ClassA如何获得ClassB的实例?一个最直接的方法是在aMethod里声明: IClassB instanceOfClassB = new ClassB(); 这里使用了一个接口IClassB。 问题是,如果出现这样的情况:继续使用ClassA,但要求用IClassB的另一个实现ClassB2代替ClassB呢?更概括一点说:ClassA怎样才能找到IClassB的具体实现?很明显,上述代码增加ClassA和ClassB的耦合度,以致于无法在不修改ClassA的情况下变更IClassB的具体实现。 IoC模 式就是用于解决这样的问题。当然,还有其他的方法,比如Service Locator模式,但现在我们只关注IoC。如前所述,IoC容器负责初始化组件(如IClassB),并将实例交给使用者。使用代码或配置文件以 声明的方式将接口与实例关联起来,IoC容 器负责进行实际的调用处理。对于调用者,只需要关注接口就行了。 根据实例传入方式的不同,IoC分为type 1 IoC(接口注入[3])、type 2 IoC(设值方法注入)和type 3 IoC(构造子注入)。分别用代码说明如下: type 1 IoC(接口注入) public interface GetClassB { void getClassB(IClassB instanceOfClassB); } class ClassA implements GetClassB… IClassB instanceOfClassB; void getClassB(IClassB instanceOfClassB) { this.instanceOfClassB = instanceOfClassB; } type 2 IoC(设值方法注入) class ClassA... IClassB instanceOfClassB; public void setFinder(IClassB instanceOfClassB) { this.instanceOfClassB = instanceOfClassB; } type 3 IoC(构造子注入) class ClassA… ClassB instanceOfClassB; public classA(IClassB instanceOfClassB) { this. instanceOfClassB = instanceOfClassB; } Spring使用的是type 2 IoC。 2、DI(Dependecy Injection)代码注入 根据实例传入方式的不同,IoC分 为type 1 IoC(接 口注入[3])、type 2 IoC(设值方法注入)和type 3 IoC(构造子注入)。在spring里的是 IOC的第二种,即设置方法注入。具体例子可以查看http://java.chinaitlab.com/Spring/727391.html (Spring 依赖注入原理学习) 3、AOP(Aspect-Oriented Programming)面向方面的编程 要理解AOP的原理,先看这篇文章,文章不长,通过例子通俗易懂的解释了AOP概念的来源以及JAVA的代理机制。http://hi.baidu.com/ayongs/blog/item/1c990a089d75c035e824886e.html 通过上文链接的文章,我们知道了在SPRING的AOP中,IoC功能用来对JAVA动态代理进行改进。来看一个例子。 使用AOP,你可以将处理aspect的代码注入主程序,通常主程序的主要目的并不在于处理这些aspect。AOP可以防止代码混乱。 为了理解AOP如何做到这点,考虑一下记日志的工作。日志本身不太可能是你开发的主程序的主要任务。如果能将“不可见的”、通用的日志代码注入主程序中, 那该多好啊。AOP可以帮助你做到。Spring framework是很有前途的AOP技术。作为一种非侵略性的,轻型的AOP framework,你无需使用预编译器或其他的元标签,便可以在Java程序中使用它。这意味着开发团队里只需一人要对付AOP framework,其他人还是象往常一样编程。 AOP是很多直觉难以理解的术语的根源。幸运的是,你只要理解三个概念,就可以编写AOP模块。这三个概念是:advice,pointcut和 advisor。advice是你想向别的程序内部不同的地方注入的代码。pointcut定义了需要注入advice的位置,通常是某个特定的类的一个 public方法。advisor是pointcut和advice的装配器,是将advice注入主程序中预定义位置的代码。 既然我们知道了需要使用advisor向主要代码中注入“不可见的”advice,让我们实现一个Spring AOP的例子。在这个例子中,我们将实现一个before advice,这意味着advice的代码在被调用的public方法开始前被执行。以下是这个before advice的实现代码:代码:package com.company.springaop.test;import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;public class TestBeforeAdvice implements MethodBeforeAdvice { public void before(Method m, Object[] args, Object target) throws Throwable { System.out.println("Hello world! (by " + this.getClass().getName() + ")"); }} 接口MethodBeforeAdvice只有一个方法before需要实现,它定义了advice的实现。before方法共用三个参数,它们提供了相 当丰富的信息。参数Method m是advice开始后执行的方法。方法名称可以用作判断是否执行代码的条件。Object[] args是传给被调用的public方法的参数数组。当需要记日志时,参数args和被执行方法的名称,都是非常有用的信息。你也可以改变传给m的参数, 但要小心使用这个功能;编写最初主程序的程序员并不知道主程序可能会和传入参数的发生冲突。Object target是执行方法m对象的引用。在下面的BeanImpl类中,每个public方法调用前,都会执行advice:代码:package com.company.springaop.test;public class BeanImpl implements Bean { public void theMethod() { System.out.println(this.getClass().getName() + "." + new Exception().getStackTrace()[0].getMethodName() + "()" + " says HELLO!"); }}类BeanImpl实现了下面的接口Bean:代码:package com.company.springaop.test;public interface Bean { public void theMethod();}虽然不是必须使用接口,但面向接口而不是面向实现编程是良好的编程实践,Spring也鼓励这样做。pointcut和advice通过配置文件来实现,因此,接下来你只需编写主方法的Java代码:代码:package com.company.springaop.test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext;public class Main { public static void main(String[] args) { //Read the configuration file ApplicationContext ctx = new FileSystemXmlApplicationContext("springconfig.xml"); //Instantiate an object Bean x = (Bean) ctx.getBean("bean"); //Execute the public method of the bean (the test) x.theMethod(); }} 我们从读入和处理配置文件开始,接下来马上要创建它。这个配置文件将作为粘合程序不同部分的“胶水”。读入和处理配置文件后,我们会得到一个创建工厂 ctx。任何一个Spring管理的对象都必须通过这个工厂来创建。对象通过工厂创建后便可正常使用。 仅仅用配置文件便可把程序的每一部分组装起来。代码:<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"><beans> <!--CONFIG--> <bean id="bean" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> <value>com.company.springaop.test.Bean</value> </property> <property name="target"> <ref local="beanTarget"/> </property> <property name="interceptorNames"> <list> <value>theAdvisor</value> </list> </property> </bean> <!--CLASS--> <bean id="beanTarget" class="com.company.springaop.test.BeanImpl"/> <!--ADVISOR--> <!--Note: An advisor assembles pointcut and advice--> <bean id="theAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice"> <ref local="theBeforeAdvice"/> </property> <property name="pattern"> <value>com\.company\.springaop\.test\.Bean\.theMethod</value> </property> </bean> <!--ADVICE--> <bean id="theBeforeAdvice" class="com.company.springaop.test.TestBeforeAdvice"/></beans> 四个bean定义的次序并不重要。我们现在有了一个advice,一个包含了正则表达式pointcut的advisor,一个主程序类和一个配置好的接 口,通过工厂ctx,这个接口返回自己本身实现的一个引用。 BeanImpl和TestBeforeAdvice都是直接配置。我们用一个唯一的ID创建一个bean元素,并指定了一个实现类。这就是全部的工作。 advisor通过Spring framework提供的一个RegexMethodPointcutAdvisor类来实现。我们用advisor的一个属性来指定它所需的 advice-bean。第二个属性则用正则表达式定义了pointcut,确保良好的性能和易读性。 最后配置的是bean,它可以通过一个工厂来创建。bean的定义看起来比实际上要复杂。bean是ProxyFactoryBean的一个实现,它是 Spring framework的一部分。这个bean的行为通过一下的三个属性来定义: * 属性proxyInterface定义了接口类。 * 属性target指向本地配置的一个bean,这个bean返回一个接口的实现。 * 属性interceptorNames是唯一允许定义一个值列表的属性。这个列表包含所有需要在beanTarget上执行的advisor。注 意,advisor列表的次序是非常重要的。Spring工具 虽然你可以手工修改Ant构建脚本,但使用SpringUI(译注:SpringUI现在是Spring framework的一部分,并改名为spring-ide),使用Spring AOP变得很简单,只要点点鼠标即可。你可以把SpringUI安装成Eclipse的一个plug-in。然后,你只需在你的project上右击鼠 标,并选择“add Spring Project Nature”。在project属性中,你可以在“Spring Project”下添加Spring配置文件。在编译前把下面的类库加入project:aopalliance.jar,commons- logging.jar,jakarta-oro-2.0.7.jar和spring.jar。运行程序时你会看到下面的信息:... (logging information)Hello world! (by com.company.springaop.test.TestBeforeAdvice)com.company.springaop.test.BeanImpl.theMethod() says HELLO!优点和缺点 Spring比起其他的framework更有优势,因为除了AOP以外,它提供了更多别的功能。作为一个轻型framework,它在J2EE 不同的部分都可以发挥作用。因此,即使不想使用Spring AOP,你可能还是想使用Spring。另一个优点是,Spring并不要求开发团队所有的人员都会用它。学习Spring应该从Spring reference的第一页开始。读了本文后,你应该可以更好地理解Spring reference了。Spring唯一的缺点是缺乏更多的文档,但它的mailing list是个很好的补充,而且会不断地出现更多的文档。
评论
回复: JAVA/J2EE, Struts, Spring, Hibernate学习笔记(ZT) Spring 依赖注入原理学习首先我们来看看 Spring 参考文档的 11.2.6. 执行SQL语句 这里有个代码片断: import javax.sql.DataSource;import org.springframework.jdbc.core.JdbcTemplate; public class ExecuteAStatement { private JdbcTemplate jt; private DataSource dataSource; public void doExecute() { jt = new JdbcTemplate(dataSource); jt.execute("create table mytable (id integer, name varchar(100))"); } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; }} 这个就是普通的 Java 类, 再参考 11.2.4. DataSource接口, 这里的另一个代码片断: DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName("org.hsqldb.jdbcDriver");dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");dataSource.setUsername("sa");dataSource.setPassword(""); 我们可以写一个测试类来执行代码: import org.springframework.jdbc.datasource.DriverManagerDataSource; public class TestTemplate { public static void main(String[] args) { // 新建一个数据源对象 DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("org.hsqldb.jdbcDriver"); dataSource.setUrl("jdbc:hsqldb:hsql://localhost:"); dataSource.setUsername("sa"); dataSource.setPassword(""); // 新建一个ExecuteAStatement 对象 ExecuteAStatement eas = new ExecuteAStatement(); // 给执行表达式的对象关联数据源(也就是常说的注入, 通过 JavaBean 的 setXxx 方法关联起来) eas.setDataSource(dataSource); // 执行功能代码 eas.doExecute(); }} 这个代码可以跑通, 就是普通的编程方式, 大家可以去看刚才介绍的文档附近的详细说明. 那么如果用 Spring 来做, 代码会变成这样:ExecuteAStatement 类代码保持不变, 多了个 beans.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <bean id="userDAO" class="ExecuteAStatement"> <property name="dataSource"> <ref bean="myDataSource" /> </property> </bean> <bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>org.hsqldb.jdbcDriver</value> </property> <property name="url"> <value>jdbc:hsqldb:hsql://localhost:</value> </property> <property name="username"> <value>sa</value> </property> <property name="password"> <value></value> </property> </bean> </beans> 测试类: import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) throws IOException { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); ExecuteAStatement eas =(ExecuteAStatement)context.getBean("userDAO"); // 执行功能代码 eas.doExecute(); }} 和上面的 TestTemplate 类相比, 就会发现 new DriverManagerDataSource() 这个过程不用我们写了, 运行的时候会发现一切都执行的好好的, 也就是常说的 ExecuteAStatement 的 dataSource 这个属性被注入了. 那么这个过程到底该如何理解呢? Spring 是一个对象池, 可以简化为一个 Map, 存多个主键和对象的映射. 那么 Spring 运行的过程中, 会根据 beans.xml 一步步进行必要的解析工作: Map springEngine = new HashMap(); OK, 解析到了<bean id="userDAO" class="ExecuteAStatement">, 发现 bean 定义, 那就新建一个实例存到对象池里吧, 主键就是 userDAO, 值就是对象:ExecuteAStatement bean1 = new ExecuteAStatement();springEngine.put("userDAO", bean1); 再往下执行, 发现 property 定义:<property name="dataSource">到了这里, 就知道应该调用 bean1.setDataSource(DataSource) 方法了. 可以接着执行, 发现<ref bean="myDataSource" />, 哦, 这个方法的参数还没有呢, 是个 bean 的引用, 好了, 要调用这个方法, 还是先 new 一个名字为 myDataSource 的 bean2 吧. 就跳到下面寻找 myDataSource 的定义, 找到了: <bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>org.hsqldb.jdbcDriver</value> </property> <property name="url"> <value>jdbc:hsqldb:hsql://localhost:</value> </property> <property name="username"> <value>sa</value> </property> <property name="password"> <value></value> </property> </bean>像以前一样, 先实例化这个类, 然后看到 property 表情就调用对应的 setXxx() 这样的方法, 相当于下面一段代码: // 新建一个数据源对象 DriverManagerDataSource bean2 = new DriverManagerDataSource(); bean2.setDriverClassName("org.hsqldb.jdbcDriver"); bean2.setUrl("jdbc:hsqldb:hsql://localhost:"); bean2.setUsername("sa"); bean2.setPassword("");不是还有个 bean 的 id 名字为 myDataSource 嘛, 那就把它存到对象池里面: springEngine.put("myDataSource", bean2); 好了, 最后就是把他们两个关联起来了, 通过 ref 里指定的 bean id 名来关联起来: // 省略类型转换的代码springEngine.get("userDAO").setDataSource(springEngine.get("myDataSource")); 最后返回给用户的就是一个对象池(一个 Map)了, 所以别人调用的时候, 就发现 springEngine.get("userDAO") 回来的类的 dataSource 属性已经被实例化过了, 这些都是 Spring 幕后工作的代码, 通过反射机制来实现. 所以最后写代码调用:context.getBean("userDAO") 的时候, 得到的是 ExecuteAStatement, 这时候还有一个 myDataSource, 也可以被调用:context.getBean("myDataSource"), 得到的是 DriverManagerDataSource. 介绍的过程, 仅供参考. 欢迎大家交流更好的原理介绍文章.
评论
回复: JAVA/J2EE, Struts, Spring, Hibernate学习笔记(ZT) spring AOP面向切面编程spring里面有个概念叫aop(面向切面编程),很好很强大又很让人费解,很多开发人员会用并且天天挂在嘴边但是不理解其核心原理,今天周末有空,我 想用一个小系列的文章给大家把aop分析清楚。要理解aop,首先要掌握java中的代理模式。 在日常生活中,会遇到各种各样的中介机构,比如猎头公司,律师事务所,婚姻介绍所,房产公司等。在这些单位工作的人员均可称为代理人。代理人的共同特征是 可以代替委托人去和第三方通信。譬如:律师代替委托人打官司,猎头代替委托人物色人才,红娘 代替委托人寻找对象,房产代理人代替委托人出租房屋。 代理人可以在第三方和委托人之间转发或过滤消息,但是不能取代委托人的任务。譬如你要找女朋友,委托你一要好的哥们去帮你物色,结果被他给物色了。这就不 叫代理。 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目 标对象之间起到中介的作用。 代理模式一般涉及到的角色有: 抽象角色:声明真实对象和代理对象的共同接口; 代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时, 代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。 真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。 我们来看个例子:代码: package com.softeem.aop.staticProxy; /** * @author leno *抽象角色 */ public interface IHello { String greeting(String who); } package com.softeem.aop.staticProxy; /** * @author leno *真实角色 */ public class HelloImpl implements IHello { public String greeting(String who) { System.out.println("greeting method is invoked....."); return "hello,"+who; } } 试想一下,如果这时候我们要对问候的业务逻辑方法进行日志记录。我们当然可以这样做:代码: package com.softeem.aop.staticProxy; /** * @author leno *真实角色 */ public class HelloImpl implements IHello { private Logger logger = Logger.getLogger(this.getClass().getName()); public void log(String message) { logger.log(Level.INFO, message); } public String greeting(String who) { log( "starting..."); System.out.println("greeting method is invoked....."); log("stopping..."); return "hello,"+who; } 可问题来了,项目经理发话,不容许修改现存的类的实现。怎么办?这时候我们就要就想到代理模式了。我们再加一个代理类:代码: 静态代理类: package com.softeem.aop.staticProxy; import java.util.logging.Level; import java.util.logging.Logger; public class HelloLoggerProxy implements IHello { private Logger logger = Logger.getLogger(this.getClass().getName()); private IHello helloImpl; public HelloLoggerProxy(IHello helloImpl) { super(); this.helloImpl = helloImpl; } public String greeting(String who) { log( "starting..."); String hello = helloImpl.greeting(who); log("stopping..."); return hello; } public void log(String message) { logger.log(Level.INFO, message); } } 客户端测试代码: package com.softeem.aop.staticProxy; public class TestStaticProxy { public static void main(String[] args) { IHello hello = new HelloLoggerProxy(new HelloImpl()); hello.greeting("leno"); } } 由以上代码可以看出,客户实际需要调用的是HelloImpl类的greeting()方法,现在用HelloLoggerProxy来代理 HelloImpl类,同样达到目的,同时还在方法调用的前后都做了日志记录。这就是静态代理。 但是,如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实色必须对应角一个 代理角色,如果大量使用会导致类的急剧膨胀;而且,如果项目中要做日志的类有100个,每个类里面有100个方法。重复代码就太可怕了。有人说,不怕,我 就一愚公。好,有天项目经理突然要求修改做日志的方式,你再看看这些方法,估计撞墙的心都有了。那怎么办?我们就改用动态代理。 JDK1.3以后提供了动态代理的支持,程序员通过实现java.lang.reflect.InvocationHandler接口提供一个执行处理 器,然后通过java.lang.reflect.Proxy得到一个代理对象,通过这个代理对象来执行商业方法,在商业方法被调用的同时,执行处理器会 被自动调用。代码: 动态代理类: package com.softeem.aop.dynamicProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.logging.Level; import java.util.logging.Logger; public class DynamicLoggerProxy implements InvocationHandler { private Logger logger = Logger.getLogger(this.getClass().getName()); private Object delegate; @SuppressWarnings("unchecked") public Object bind(Object delegate) { this.delegate = delegate; Class cls = delegate.getClass(); return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), this); } public Object invoke(Object o, Method method, Object[] args) throws Throwable { log( "starting..."); Object obj = method.invoke(delegate, args); log("stopping..."); return null; } public void log(String message) { logger.log(Level.INFO, message); } } 客户端测试代码: package com.softeem.aop.dynamicProxy; public class TestDynamicProxy { public static void main(String[] args) { IHello hello = (IHello) new DynamicLoggerProxy().bind(new HelloImpl()); hello.greeting("leno"); } } 大家看到,一个动态代理类就代替了无数个静态代理类。一劳永逸。这里涉及到一些java反射的知识,我会在以后单独讲述。 java的动态代理非常实用和强大,可它有一个前提,需要我们的处理业务逻辑的类必须至少实现一个接口,虽然面向接口编程是 需要提倡的,但如果我们有些现存的类就是没有实现接口,那如何代理呢?这就需要CGLIB的帮助了。继续改进我们的代码: 没有实现任何接口的类:代码: package com.softeem.aop.cglibProxy; public class Hello{ public void greeting(String who) { System.out.println("hello,"+who); } } CGLIB代理类: package com.softeem.aop.cglibProxy; import java.lang.reflect.Method; import java.util.logging.Level; import java.util.logging.Logger; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CGLIBLoggerProxy implements MethodInterceptor { private final Logger logger = Logger.getLogger(this.getClass().getName()); public Object bind(Object delegate) { Enhancer enhancer = new Enhancer(); enhancer.setCallback(this); enhancer.setSuperclass(delegate.getClass()); return enhancer.create(); } public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable { log( "starting..."); proxy.invokeSuper(o, args); log("stopping..."); return null; } public void log(String message) { logger.log(Level.INFO,message); } } 客户端测试代码: package com.softeem.aop.cglibProxy; public class TestCGLIBProxy { public static void main(String[] args) { Hello hello = (Hello) new CGLIBLoggerProxy().bind(new Hello()); hello.greeting("leno"); } } 好了,有了动态代理和CGLIB,那我们就可以给任何实际的类提供代理了。从而可以在我们的代理类中加入一些与业务逻辑无关的系统级的功能服务,如:日志 记录,事务处理,安全管理等。而且不会影响到我们现有的系统。看起来似乎很完美 了。但是且慢,如果我们的应用中有些需要这些系统级的功能服务,而有些又不需要呢?如果把代码写死了显然达不到我们的要求。怎么办?这时候就要用到一个非 常重要的思想:用配置代替编码。http://java.chinaitlab.com/Spring/751613_2.html 这里就开始运用SPRING的IOC配置了。我们通过SPRING的一个例子看SPRING怎么样通过IOC将JAVA的代理机制变成SPRING的 AOP。http://hi.baidu.com/ayongs/blog/item/b971923d9d0d0905bba167e9.html
评论
回复: JAVA/J2EE, Struts, Spring, Hibernate学习笔记(ZT)Spring学习总结在MVC架 构中,Spring主要完成C层,Sturts主要完成V层,Hibernate主要完成M层,Spring主要解决了对象创建和依赖,让Spring来管理我们对象的创建和依赖,Spring采 用注入(DI)的 方式来实现. 简 单来说,Spring是 一个轻量级的控制反转(IoC)和面向切面(AOP)的 容器框架. 1.Spring相对于EJB是非常小的一个框架,并且不依赖于特定的类,是非侵入式的. IoC(控制反转)的概念:本来是由应用程序管理的对象 之间的依赖关系,现在交给了容器管理,这就叫控制反转,即交给了IoC容器,Spring的IoC容 器主要使用DI方 式实现的。不需要主动查找,对象的查找、定位和创建全部由容器管理. 2.Spring提供了面向切面编程(AOP)的丰富支持。Spring和Struts集成配置: (1)、spring和struts的 依赖包配置 * struts --拷贝struts和jstl的 依赖包 --在web.xml文 件中配置ActionServlet --提供struts-config.xml文 件 --提供国际化支持,提供缺省的国际化资源文件 * spring --拷贝spring相 关依赖包 --提供spring的 配置文件 (2)在web.xml文 件中配置ContextLoaderListener,让Web Server在启动的时候将BeanFactory放 到ServletContext中 <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> (3)Struts-config.xml文 件中<action>标 签的type属 性需要更改为Spring的 代理Action类:org.springframework.web.struts.DelegatingActionProxy 代理Action的 作用:取得BeanFactory, 然后到IoC容 器中将本次请求对应的Action取出 (4)将Action交 给Spring创 建,必须配置业务逻辑对象,注入给Action <bean name="/login" class="com.bjpowernode.usermgr.web.actions.LoginAction"> <property name="userManager" ref="userManager"/> </bean> * 必须使用name属 性,而且name属 性的值必须和struts-config.xml文 件中<action>标 签的path属 性值一致 * 必须配置业务逻辑对象 * 建议将scope设置为prototype, 这样struts的Action将 是线程安全的. Spring和Hibernate集 成的方法: (1)声 明式事务配置 * 配置SessionFactory * 配置事务管理器 * 事务的传播特性 * 那些类那些方法使用事务 <!-- 配置SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation"> <value>classpath:hibernate.cfg.xml</value> </property> </bean> <!-- 配置事务管理 器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref bean="sessionFactory"/> </property> </bean> <!-- 那些类那些方 法使用事务 --> <aop:config> <aopointcut id="allManagerMethod" expression="execution(* com.bjpowernode.usermgr.manager.*.*(..))"/> <aop:advisor pointcut-ref="allManagerMethod" advice-ref="txAdvice"/> </aop:config> <!-- 事务的传播特 性 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="del*" propagation="REQUIRED"/> <tx:method name="modify*" propagation="REQUIRED"/> <tx:method name="*" propagation="REQUIRED" read-only="true"/> </tx:attributes> </tx:advice> (2)编 写业务逻辑方法 * 继承HibernateDaoSupport类, 使用HibernateTemplate来 持久化,HibernateTemplate是 Hibernate Session的 轻量级封装 * 默认情况下运行期异常才会回滚(包括继承了RuntimeException子 类),普通异常是不会滚的 * 编写业务逻辑方法时,最好将异常一直向上抛出,在表示层 (struts) 处理 * 关于事务边界的设置,通常设置到业务层,不要添加到Dao上
评论
回复: JAVA/J2EE, Struts, Spring, Hibernate学习笔记设计模式(Patterns in Java)http://www.jdon.com/designpatterns/A.创建模式 设计模式 之Factory(工厂模式) 使用工厂模式就象使用new一样频繁.2002/10/9更新 设计模式之 Prototype(原型模式) 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 设计模式之Builder 汽车由车轮 方向盘 发动机很多部件组成,同时,将这些部件组装成汽车也是一件复杂的工作,Builder模式就是将这两种情况分开进行。 设计模式之 Singleton(单态模式) 保证一个类只有一个实例,并提供一个访问它的全局访问点 2002/10/9更新 B.结构模式 设计模式 之Facade 可扩展的使用JDBC针对不同的数据库编程,Facade提供了一种灵活的实现. 设计模式之 Proxy 以Jive为例,剖析代理模式在用户级别授权机制上的应用 设计模式之Adapter 使用类再生的两个方式:组合(new)和继承(extends),这个已经在"thinking in java"中提到过. 设计模式之Composite 就是将类用树形结构组合成一个单位.你向别人介绍你是某单位,你是单位中的一个元素,别人和你做买卖,相当于和单位做买卖。文章中还对Jive再进行了剖 析。 设计模式之Decorator Decorator是个油漆工,给你的东东的外表刷上美丽的颜色. 设计模式之Bridge 将"牛郎织女"分开(本应在一起,分开他们,形成两个接口),在他们之间搭建一个桥(动态的结合) 设计模式之Flyweight 提供Java运行性能,降低小而大量重复的类的开销. C.行为模式 设计模式之Template 实际上向你介绍了为什么要使用Java 抽象类,该模式原理简单,使用很普遍. 设计模式之Memento 很简单一个模式,就是在内存中保留原来数据的拷贝. 设计模式之Observer 介绍如何使用Java API提供的现成Observer 设计模式之Chain of Responsibility 各司其职的类串成一串,好象击鼓传花,当然如果自己能完成,就不要推委给下一个. 设计模式之Command 什么是将行为封装,Command是最好的说明. 设计模式之 State 状态是编程中经常碰到的实例,将状态对象化,设立状态变换器,便可在 状态中轻松切换. 设计 模式之Strategy 不同算法各自封装,用户端可随意挑选需要的算法. 设计模式之Mediator Mediator很象十字路口的红绿灯,每个车辆只需和红绿灯交互就可以. 设计模式之 Interpreter 主要用来对语言的分析,应用机会不多. 设计模式之Visitor 访问者在进行访问时,完成一系列实质性操作,而且还可以扩展. 设计模式之Iterator 这个模式已经被整合入Java的Collection.在大多数场合下无需自己制造一个Iterator,只要将对象装入Collection中,直接使 用Iterator进行对象遍历。更多Iterator专题
评论
回复: JAVA/J2EE, Struts, Spring, Hibernate学习笔记Java SCJP 英语词汇表Abstract Window Toolkit(AWT) 抽象窗口工具包 Abstraction 抽象 Anonymous class 匿名类 Anonymous inner class 匿名内部类 Application Programming Interface (API)应用程序接口 Array 数组 Attribute 属性 Base class 基类/父类 Byte stream 字节流 Casting 类型转换 Character stream 字符流 Character 字符 Child class 子类 Class 类 Class member 类的成员 Class method 类的方法 Class variable 类变量 Collection interface Collection接口 Constructor 构造方法 Container 容器 Data Definition Language(DDL) 数据定义函数 Data source 数据源 Data Management System(DBMS) 数据库管理系统 Declaration 声明 Derived Class 派生类/子类 Encapsulation 封装 Event 事件 Event source 事件源 Exception 异常 Exception handling 异常处理 Garbage collection 垃圾回收机制 Generalization 一般化,泛化 Graphics User Interface (GUI) 图形用户界面 Identifier 标识符 Inheritance 继承 Inner class 内部类 Instance 实例 Integrated Development Environment (IDE) 继承开发环境 Interface 接口 Java Database Connectivity (JDBC) Java数据库连接 Java Development Kit(JDK) Java开发工具包 Java Foundation Class (JFC) Java基础类 Java Runtime Environment(JRM) Java运行时环境 Java Virtual Machine (JVM) Java虚拟机 Keyword 关键字 Layout manager 布局管理器 Local variable 局部变量 Member 成员 Meta data 元数据 Method 方法 Modifier 修饰符 Multithread 多线程 Object 对象 Object Oriented Programming (OOP) 面向对象编程 Open DataBase Connectivity (ODBC) 开放式数据库连接 Overloaded method 重载方法 Overridden method 重写方法 Package 包 Parent class 父类 Platform independent 跨平台 Polymorphism 多态 Runtime exception 运行时异常 Structured Query Language (SQL) 结构化查询语言 Sub class 子类 Super class 超类/父类 Synchronized method 同步方法 Thread 线程 Uniform Resource Locator (URL) 统一资源定位器 下面的英语词汇是本人准备SCJP所整理的,现在跟大家分享一下: encapsulation--封装性 break encapsulation 破坏了封装性duplicate------重复invoke---------引用template-------模板conventions----公约contract-------合同,契约,规范,缩短 expand or contract---变大与缩小identifiers----标识符keywords-------关键字inheritance----继承general--------普通generate-------产生 explicitly-----明确cohesive-------凝聚力recommendations建议adhere---------坚持tricky --------绝招spec-----------规格compose--------组成 enhancement----增强a set of-------一组cleverly-------巧妙internationally国际 currency character货币符号$curly braces---花括号{} comma----------逗号,semicolon------分号;parentheses----圆括号()dot------------圆点.ellipsis-------省略号……square brackets方括号[]angle brackets-尖括号<> postfix--------后缀 也可以用suffix来表示prefix---------前缀preceding------先前的 valid----------有效的inferred-------推断retrieve ------重新找到,取回method signatures方法签名objective------目标, 目的guarantee------保证scope----------范围, 机会, 余地 modifiers------修饰词---------access modifiers----访问权限polymorphically多态polymorphism---多态性collectively---全体的,共同的crucial--------至关紧要identical------一样的--------almost identical-----差不多essentially ---本质上 more than------而不是other than-----除了,不同于but rather-----而是anything but---除了……之外的任何东西; 绝不; regardless-----不管Variable Argument Lists可变形参列表clarify--------澄清,阐明syntax---------语法Primitive------基本类型presented------介绍fragments------片段compile--------编译 compilable-------可编译的 collision------冲突duplicates-----副本three-dimensional array 三维数组 restrict-------约束i.e.-----------也就是enclosed-------被附上的,依附于nuances--------细微差别concrete class-具体的类,即非abstract类spot-----------认出,发现immutable------不可改变的inheritance----继承hierarchies----层次encapsulation--包装,封装and theses-----形形色色的-----------and graduate theses 形形色色的大学毕业生dedicated to---献身于that is,------换句话说In a nutshell--简单的说diamond--------钻石,菱形hint-----------提示,暗示,线索Overriding-----覆盖-Overloading---重载 overriding method子类中的覆盖方法overriden method父类中的被覆盖方法checked exception===RuntimeExceptionunchecked exception==非runtime exceptionpass the buck to推卸责任给……Covariant Returns协变返回assign----------赋值 Coupling--------耦合Cohesion--------结合,聚合up front--------预先 admit it up front------预先接纳With respect to 关于fragments ------片段respective------各自的For the most part在极大程序上 decimal----------十进制octal-------------八进制hexadecimal ------十六进制decimal fraction--小数 implicit----------暗示的 explicit-----直接的Variable Scope----变量作用域 Wrapper Classes---封装类,如Boolean,ChracterunBoxing------------拆包------autoboxing-------封装包Likewise----------同样地 eligible----------符合条件 eligible for garbage collection----符合垃圾回收器的条件emptied-----------耗尽reclaimed---------回收,再生boils down to-----归结为contrary to-------与什么相反candidates--------考生,候选人operands----------操作数 Remainder Operator-- 余数reminder-------------提醒remainder------------余数 evaluate----------求值rightmost---------最右边的ternary operator--三元操作符Short-Circuit----使……短路recursion--------递归mythical---------神话is out of--------脱离危险Side Effects-----副作用 So far so good---到现在为止,一直都还很好backwards and forwards来回地 sets aside-------留出as if by magic不可思议的Calendaring------日历 Locale-----------现场checkered--------多变的delimiters-------定界符get away with it-侥幸成功,逃脱处罚from Within------从……的内部is subject to----从属于……;受……支配issued from------由…&hellip[SIZE=+0];产生In addition to ……also 除了……外,还可以…… alias------------别名cries out for----迫切需要be back----------来回concurrently-----并发的be in for--------要遭遇^daemon threads---守护线程,即后台线程[/SIZE]
评论
回复: JAVA/J2EE, Struts, Spring, Hibernate学习笔记我靠 这是我记忆里面家园的第一次的技术贴阿 强贴留名
评论
[SIGPIC][/SIGPIC] 赏 反馈:mogusaen 和 (已删除的会员) 2010-05-23#9
老衲法号乱来
729 $0.00 回复: JAVA/J2EE, Struts, Spring, Hibernate学习笔记Struts, Spring, Hibernate是国内典型的SSH 不过个人认为这里不是最流行评论
[SIGPIC]Struts, Spring, Hibernate是国内典型的SSH 不过个人认为这里不是最流行 点击展开...我以前在日本用的是SSH,先把这方面的技术巩固一下,应付面试。你觉得还有那些技术需要掌握的,请指教。
评论
回复: JAVA/J2EE, Struts, Spring, Hibernate学习笔记我面试过不少人 同胞 西人 阿X 有些面试程序员的经验 希望能对你有帮助 首先IOC以及AOP现在都需要通过annotation inject而不再是通过XML discriptor bind 同理 HBM也是一样 HB的search以及validator很重要 尤其是validator在EE6已经变成了JSR303的规范 同时 HBM与JPA的差异也需要注意 对于HB细节的把握 是体现技术能力的地方比如 看看这个blog http://clarkupdike.blogspot.com/2007/01/hibernate-mappedby-to-superclass.html 里面的应用 如果你用到过这里提及的运用 说明你对于HB的使用达到了一个比较高的水准。如果你以前没用过,也可以借鉴下。 我面试Hibernate方面问题 一般就提3个问题 1个就是这这个OneToMany polymorphism的处理问题 还有一个是如何同时eager load两个OneToMany的collection 第3个就是Hibernate与Cache的运用 关于Hibernate与Cache应用 我还和Gavin King进行过一些讨论 由于工作关系 我和hibernate的core team有着比较紧密地合作 如果你有兴趣 我们可以进一步交流下 Struts作为action base的MVC framework在很长一段时间内占有统治地位 即使现在大量的legacy系统还是沿用这类框架 同样对于Struts细节的把握 也能体现你的Senior程度 比如 "actionForm的reset 在Struts的整个lifeCycle里面有什么作用" 与此同时 Seam (JSF 1.2+ Facelet+RichFaces) 或者JSF 2.0这里event driven的MVC framework在EE5以及EE6(CDI)变成了de facto的WEB标准 能够区别action base/event base的MVC framework也是一个需要关注的地方 RIA也是趋势 Flex结合BlazeDS是个非常组合 SJCP没有任何用处 你有Spring的基础 可以考虑SpringSource的certification http://www.springsource.com/training/certification这个比较能忽悠人 基本就这些了 看看有哪些可以进一步的
评论
[SIGPIC][/SIGPIC] 赏 反馈:Candace Gao 和 (已删除的会员) 2010-05-23#12 8,562 $0.00 回复: JAVA/J2EE, Struts, Spring, Hibernate学习笔记多谢高手指点。你说的知识点我会注意学习的。我是一个项目做了4年,看来有很多知识需要更新了。希望面试的时候不要碰见Cayman。。。
评论
mogusaen 说:多谢高手指点。你说的知识点我会注意学习的。我是一个项目做了4年,看来有很多知识需要更新了。希望面试的时候不要碰见Cayman。。。点击展开...AOP技术是比较成熟了,但是还没有成为主流,一种观点认为,AOP提出了好多新的概念,比如aspect,advice,joint point, product等,但大多数的developers还没有准备好使用它。AOP的在JEE里主要应用于这两个方面:declarative transaction management and securities, 使用AOP后业务代码可以不用考虑transaction and security的细节。所以建议只作为简单了解,不要花太多经历在这上面。Spring vs JEE5&6Spring的创始人Rod Johnson是JEE的坚决反对者,认为JEE没有必要这么复杂。这个argument对于J2EE1.4以前的版本,我是举双手赞成的,但是JEE5之后,JEE做了大量的简化,从Spring和Hibernate "unabashfully" copied很多东西过来,所以现在JEE已经不那么复杂了。WEB Service + Session Bean + JPA(Hibernate)应该是主流趋势。 在这种趋势下,Spring可能只能被逼到做Web层的应用了,无法成为业务逻辑层的主流,再加上Spring已经被过度商业化炒作,有谁敢保证哪一天它不会停止开源这种运作模式呢?其实对于用户来说,最核心的资产还是数据,应用程序可以不断升级换代,但数据就不一样,一旦定型,多个系统可能共享一个数据库系统,是不方便变更的(very difficult for refactoring)。特别是对于mission-critical的系统,数据库是不能shutdown的。Hibernate vs ERD对于数据库的设计,到底从传统的数据库设计ERD开始呢,还是从OO设计出发,将一些java classes nominate为entities,直接generate tables呢?我个人觉得从ERD->Hibernate,这样可能不太OO,但对于建立业务数据的概念模型CDM非常有效,成熟可靠,一些业务规则可以方便的使用比如oracle pl/sql实现,维护也方便。从oo->ERD,则需要处理由one-to-many/many-to-one等出现的polymorphism的mapping问题。总之,两种方式各有利弊,一个实际的系统应该是二者的结合,需要 trade-offs。
评论
赏 我面试过不少人 同胞 西人 阿X 有些面试程序员的经验 希望能对你有帮助 首先IOC以及AOP现在都需要通过annotation inject而不再是通过XML discriptor bind 同理 HBM也是一样 HB的search以及validator很重要 尤其是validator在EE6已经变成了JSR303的规范 同时 HBM与JPA的差异也需要注意 对于HB细节的把握 是体现技术能力的地方比如 看看这个blog http://clarkupdike.blogspot.com/2007/01/hibernate-mappedby-to-superclass.html 里面的应用 如果你用到过这里提及的运用 说明你对于HB的使用达到了一个比较高的水准。如果你以前没用过,也可以借鉴下。 我面试Hibernate方面问题 一般就提3个问题 1个就是这这个OneToMany polymorphism的处理问题 还有一个是如何同时eager load两个OneToMany的collection 第3个就是Hibernate与Cache的运用 关于Hibernate与Cache应用 我还和Gavin King进行过一些讨论 由于工作关系 我和hibernate的core team有着比较紧密地合作 如果你有兴趣 我们可以进一步交流下 Struts作为action base的MVC framework在很长一段时间内占有统治地位 即使现在大量的legacy系统还是沿用这类框架 同样对于Struts细节的把握 也能体现你的Senior程度 比如 "actionForm的reset 在Struts的整个lifeCycle里面有什么作用" 与此同时 Seam (JSF 1.2+ Facelet+RichFaces) 或者JSF 2.0这里event driven的MVC framework在EE5以及EE6(CDI)变成了de facto的WEB标准 能够区别action base/event base的MVC framework也是一个需要关注的地方 RIA也是趋势 Flex结合BlazeDS是个非常组合 SJCP没有任何用处 你有Spring的基础 可以考虑SpringSource的certification http://www.springsource.com/training/certification这个比较能忽悠人 基本就这些了 看看有哪些可以进一步的点击展开...Hi there Cayman.S,Normally where and how do you collect the resumes of candidates for your vacant positions? I'm a PR holder but stil in Beijing waiting for the right time to go to Canada. Recently I sent my resumes to Monster and Workopolis, there have been no responses at all. Hope to see your feedback.
评论
赏 Hibernate vs ERD两种方式各有利弊,一个实际的系统应该是二者的结合,需要 trade-offs。点击展开...我爱Hibernate
评论
[SIGPIC]Hi there Cayman.S, Normally where and how do you collect the resumes of candidates for your vacant positions? I'm a PR holder but stil in Beijing waiting for the right time to go to Canada. Recently I sent my resumes to Monster and Workopolis, there have been no responses at all. Hope to see your feedback.点击展开...我们有合作多年的Agent 帮我们pre-screen 一般都能找到一些不错的candidate 我们不直接在Monster或者Workopolis放广告 这样会浪费更多时间 令人满意的resume多数是阿X的 面下来却是非常水 同胞的也有 虽然不多 但是都非常强
评论
[SIGPIC]我们有合作多年的Agent 帮我们pre-screen 一般都能找到一些不错的candidate 我们不直接在Monster或者Workopolis放广告 这样会浪费更多时间 令人满意的resume多数是阿X的 面下来却是非常水 同胞的也有 虽然不多 但是都非常强点击展开...非常感谢
评论
赏 我们有合作多年的Agent 帮我们pre-screen 一般都能找到一些不错的candidate 我们不直接在Monster或者Workopolis放广告 这样会浪费更多时间 令人满意的resume多数是阿X的 面下来却是非常水 同胞的也有 虽然不多 但是都非常强点击展开...
评论
回复: JAVA/J2EE, Struts, Spring, Hibernate学习笔记作java开发的路过。struts, hibernate and spring都用过,但不深入。等有时间仔细看贴学习。
评论
回复: JAVA/J2EE, Struts, Spring, Hibernate学习笔记我们有合作多年的Agent 帮我们pre-screen 一般都能找到一些不错的candidate 我们不直接在Monster或者Workopolis放广告 这样会浪费更多时间 令人满意的resume多数是阿X的 面下来却是非常水 同胞的也有 虽然不多 但是都非常强点击展开...严重同意啊。我们公司的印巴人都比较能吹,脚踏实地干活的真不多。倒是中国人说的少,做的多、好,只是英语没有他们那么溜。
·中文新闻 悉尼铁路工会纠纷:避免火车混乱的协议细节浮出水面
·中文新闻 为什么比尔·肖顿体现了澳大利亚政治最好和最坏的一面