1.Spring基础1.1.开发应用时的一些问题1.1.1.问题一:依赖在程序中要分层,且层与层之间要使用接口,就会有如下代码:以上代码是有问题的,即“在Service中引用的具体的实现类”,这样就和具体的实现类耦合在了一起,如果要更换(比如要换成OracleUserDaoImpl),就需要修改源代码。怎么样才能不依赖实现类呢?可以使用工厂模式,让UserDao的实现在在工厂中生成,而工厂是可以配置的,如下:publicclassUserServiceImpl{privateUserDaouserDao=newMySQLUserDaoImpl();//...}以上代码就是通过工厂实现的与实现类的解耦,这种情况下如果想要更新别外一个实现类,只需要修改配置文件就可以了。再想想如果对象有很多,且互相依赖,并且有的对象需要单例模式,有的则需要多个实例,这又怎么办呢?那就要再完善一下这个工厂类了,让工厂可以处理这些问题,这就是一个复杂一点的工厂类了。1.1.2.问题二:事务控制对于事务,可以使用Filter或是Struts2的拦截器实现,但这样有一些不好的地方:1,这是在显示层管理的事务,事务太长。//一、定义工厂类publicclassObjectFactory{//用于存放“对象名--实现类的全名”这种对应关系的键值对集合privatestaticPropertiesproperties;static{//读取配置文件ObjectFactory.properties,具体代码略。properties.load(inStream);}//可创建对象实例的工厂方法,接受的参数是对象名,如UserDao、RoleDao等publicstaticObjectcreateInstance(Stringname){//首先根据名称获取对应的实现类的类名,要是全限定名才行(带包名的)StringimplClassName=properties.getProperty(name);//通过反射生成实例并返回(没有处理异常)returnClass.forName(implClassName).newInstance();}}//二、使用工厂生成实例#UserDao=cn.itcast.dao.impl.MySQLUserDaoImpl#UserDao=cn.itcast.dao.impl.OracleUserDaoImplUserDao=cn.itcast.dao.impl.MySQLUserDaoImpl//三、使用工厂生成实例publicclassUserServiceImpl{privateUserDaouserDao=(UserDao)ObjectFactory.createInstance(UserDao);//...}2,有的action方法没有用到数据库操作,不需要开事务。3,不能针对某个具体功方法配置事务是否是只读的,因为有的方法只是查询数据。...如果能在业务层管理事务就更好了。这可以在每个业务方法中都写上管理事务的代码,但这样代码太多,也可以使用代理的方式实现(如JDK的动态代理)。1.2.概念:控制反转(IOC,InversionofControl)publicclassPersonServiceBean{privatePersonDaopersonDao=newPersonDaoBean();publicvoidsave(Personperson){personDao.save(person);}}PersonDaoBean是在应用内部创建及维护的。所谓控制反转就是应用本身不负责依赖对象的创建及维护,而是由外部容器负责的。这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转。控制反转即IoC(InversionofControl),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。IoC是一个很大的概念,可以用不同的方式来实现。例如:1依赖查找(DependencyLookup):容器提供回调接口和上下文环境给组件。EJB和ApacheAvalon都使用这种方式。2依赖注入(DependencyInjection):组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。后者是时下最流行的IoC类型。1.3.概念:依赖注入(DI,DependencyInjection)当我们把依赖对象交给外部容器负责创建,那么PersonServiceBean类可以改成如下:publicclassPersonServiceBean{privatePersonDaopersonDao;//要有getter与setter//通过构造器参数,让容器把创建好的依赖对象注入进PersonServiceBean//当然也可以使用setter方法进行注入。publicPersonServiceBean(PersonDaopersonDao){this.personDao=personDao;}publicvoidsave(Personperson){personDao.save(person);}}所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中。1.4.概念:面向切面编程(AOP,AspectOrientedProgramming)AOP为AspectOrientedProgramming的缩写,意为:面向切面编程(也叫面向方面),可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序统一添加功能的一种技术。主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等。使用JDK的动态代理可以实现AOP,如下图所示。1.5.Spring简介Spring是一个开源的控制反转(IoC)和面向切面(AOP)的容器框架。它的主要目是简化应用的开发。Spring的IOC容器包含并管理应用对象的配置和生命周期,你可以配置你的每个bean如何被创建,也可以配置每个bean是只有一个实例,还是每次需要时都生成一个新的实例,以及它们是如何相互关联的。Spring提供了很多基础的与业务逻辑无关的功能,比如:事务管理、持久化框架集成等等。Spring的模块图如下所示:Spring以一种非侵入式的方式来管理你的代码,Spring提倡”最少侵入”,这也就意味着你可以适当的时候安装或卸载Spring。Spring是一个轻量级容器架构。怎么区争一个框架是属于轻量级框架还是属于重量框架呢?其实划分一个应用是否属于轻量级还是重量级,主要看它使用了多少服务。使用的服务越多,容器要为普通java对象做的工作就越多,必然会影响到应用的发布时间或者运行性能,就属于重量级的,反之就是轻量级的。对于spring容器,它提供了很多服务,但这些服务并不是默认为应用打开的,应用需要某种服务,就需要指明使用该服务。如果应用使用的服务很少,如:只使用了spring核心服务,那么我们可以认为此时应用属于轻量级的,如果应用使用了spring提供的大部分服务,这时应用就属于重量级。目前EJB容器就因为它默认为应用提供了EJB规范中所有的功能,所以它属于重量级。Spring框架的主页:下载地址:使用Spring有什么好处在项目中引入spring立即可以带来下面的好处降低组件之间的耦合度,实现软件各层之间的解耦。可以使用容器提供的众多服务,如:事务管理服务、消息服务等等。当我们使用容器管理事务时,开发人员就不再需要手工控制事务.也不需处理复杂的事务传播。容器提供单例模式支持,开发人员不再需要自己编写实现代码。容器提供了AOP技术,利用它很容易实现如权限拦截、运行期监控等功能。容器提供的众多辅作类,使用这些类能够加快应用的开发,如:JdbcTemplate、HibernateTemplate。Spring对于主流的应用框架提供了集成支持,如:集成Hibernate、JPA、Struts等,这样更便于应用的开发。一、如果使用Spring,我们就不再需要手工控制事务:使用Spring后,代码变为:@TransactionalPublicvoidsave(){sessionFactory.getCurrentSession().save(info);}二、如果使用spring,我们也不需要处理复杂的事务传播行为publicvoidpayment(){Bean1.update();//更新金额Bean2.save();//记录操作日志}如果我们不使用Spring,针对下面这两种业务需求,我们该如何做?第1种可能的业务需求:要求Bean1.update()和Bean2.save()在同一个事务中执行。第2种可能的业务需求:要求不管Bean1.update()的事务是否成功,都需要记录操作日志。publicclassBean1{publicvoidupdate(){//注意:下面省略了一些代码Connectionconn=null;conn.setAutoCommit(false);Statement.executeUpdate(“updateaccountsetamount=?whereid=?);}}publicclassBean2{publicvoidsave(){//注意:下面省略了一些代码Connectionconn=null;conn.setAutoCommit(false);Statement.executeUpdate(“insertintoLog(content)values(?));}}使用Spring,我们只需要通过声明式的事务属性配置就可以轻松地实现这两种业务需求1.要求Bean1.update()和Bean2.save()的在同一个事务中执行2.要求不管Bean1.update()的事务是否成功,都需要记录日志。@Transactional(propagation=Propagation.Required)publicvoidpayment(){Bean1.update();//更新金额Bean2.save();//记录日志}publicclassBean1{@Transactional(propagation=Propagation.Required)publicvoidupdate(){executeUpdate(“updateaccountsetamount=?whereid=?);}}publicclassBean2{@Transactional(propagation=Propagation.RequiresNew)publicvoidsave(){executeUpdate(“insertintoLog(content)values(?));}}1.7.Spring3.0与Spring2.5Spring2.5的包结构。支持JDK1.4。不支持泛型。必须进行强制类型转换。Spring3.0的包结构。Jdk1.5以上。支持根据BeanID获取Bean实例,支持泛型。支持根据类名-接口名获取实例。2.第一个Spring程序(V2.5)2.1.准备开发环境2.1.1.添加jar包dist/spring.jar(核心包)lib/jakarta-commons/commons-logging.jar(日志)如果使用了切面编程(AOP),还需要下列jar文件:lib/aspectj/aspectjweaver.jar和aspectjrt.jarlib/cglib/cglib-nodep-2.1_3.jar如果使用了JSR-250中的注解,如@Resource/@PostConstruct/@PreDestroy,还需要下列jar文件:lib\j2ee\co