Spring的定义
Spring是一个全方位的应用程序框架,其的核心是一个轻量级的容器,提供一种非入侵的框架,通过Ioc注入管理,以及提供AOP、持久层、事务、MVC-web框架以及其他一些企业应用的常用服务进行了一致性的封装。
IoC:宏观上实现Ioc有两种方法,第一是依赖注入(DependencyInjection),其二是ServiceLocator。Spring采用的是第一种DependencyInjection ( 三种类型):
Type1IoC ――接口注入方式,缺点是有较强的入侵性,降低了组件的重用性;
Type2IoC ――透过设值注入,Setter()方法也是默认的注入方式;
Type3IoC ―― 透过构造器方法注入, 在XML中通过
<constructor-tagindex=”n”>
<value>YourType</value>
</constructor-tag> 进行定义。
BeanFactory主要负责Bean的配置管理(加载、生成实例、维护Bean与其他Bean之间的依赖关系,负责Bean的生命周期等)。ApplicationContext接口作为更好的替代BeanFactory的方案,提供更为完整的功能(+获取资源文件的方法、文字信息解析的方法、II8N以及发布&接收事件),其常用的三个实现类分别是:
org.springframework.context.support.FileSystemXmlApplicationContext
org.springframework.context.support.ClassPathXmlApplicationContext
org.springframework.web.context.WebApplicationContext
自动注入方式的定义属性autowire和dependency:
<beanid=”yourName” class=”yourClass”autowire=自动识别标识dependency=依赖检查标识/>
<property>…</ property >
</bean>
四种自动识别标识in{byName / byType / constructor / autodetect },
四种依赖检查标识in{simple / objects / all / none}
Aware相关接口:尽管对于大多数情况来说,最佳的情况是被Spring管理的Bean不知道自己正被Spring容器所管理,但是在某些情况下,必须让Bean使用一些Spring容器的高级功能,因此Spring提供了一些Aware相关的接口实现这种需求,主要有3个:
org.springframework.beans.factory.BeanNameAware
org.springframework.beans.factory.BeanFactoryAware
org.springframework.context.ApplicationContextAware
BeanPostProcessor接口(org.springframework.beans.factory.config.BeanPostProcessor):用来在Bean的依赖关系由Spring建立并设定完成后,还能通过BeanPostProcessor接口编写一些对Bean的修正相关属性的操作。
BeanFactoryPostProcessor接口(org.springframework.beans.factory.config.BeanFactoryPostProcessor:
用于在BeanFactory加载Bean定义文件的所有内容,但尚未正式产生Bean的实例钱对Bean进行一些处理。
org.springframework.beans.factory.config.CustomEditConfigurer实现BeanFactoryPostProcessor接口,可以读取实现java.beans.porpertyEditor接口的类,并依当中的实现,将字符串转换成制定的类型的对象,借由设计实现propertyEditor接口的类。
ApplicationContext接口实现了ResourceLoader接口提供了一个getResource()方法,通过指定资源文件的URL来取得一个实现Resource接口的实例,提供了对资源文件的泛型访问。
ApplicationContext同时还继承了MessageResource接口,提供了一个getMessage()的各型重载方法,从而实现了国际化的功能。
Spring的事件
在Spring应用程序执行期间,ApplicationContext本身会发布一系列事件,所有的时间都是org.springframework.context.ApplicationEvent的子类:
ContextClosedEvent ―――在ApplicationContext关闭时发布的事件;
ContextRefreshedEvent―――在ApplicationContext初始化或Reflesh时发布的事件;
ContextHandleEvent ―――在Web应用中,当请求被处理时,ApplicationContext会发布此事件。
事件的监听接口(org.springframework.context.ApplicationListener)有两个实现类:
ConsoleListener 仅用在Debug时在文字模式下显示记录ApplicationListener的相关消息;
PerformanceMonitorListener 用在Web应用中,搭配WebApplicationContext记录请求相应的时间。
事件的发布可以通过ApplicationContext的publishEvent()方法。
Spring-AOP
Aspect(切面):在服务流程中插入与业务逻辑无关的系统服务逻辑,称为Cross-cutting-concerns(横切关切点),被独立设定出来的Cross-cutting-concerns特殊对象称为Aspect(切面)。在AOP中着重于Aspect的辨认,将之从业务流程中独立出来,在需要该服务的时候,织入至相应的程序上,不需要服务的时候能立即从程序中脱离,应用程序中的可重用组件不用作任何的修改。在Spring中的Adivce用java语言来进行编写,在定义PointCut时使用XML配置。
Advice(处理逻辑):Aspect的具体实现称为Advice,在某个连接点所采用的处理逻辑。
Target:一个Advice被应用的对象或目标对象。
Weave(织入):将AspectObject与所服务的逻辑关联称为Weave(织入),织入有三个时间控制点: 1>编译期;2>.类加载期;3>.运行期。Spring-AOP是在运行期进行织入的。
JoinPoint(连接点):程序运行过程中的某个阶段点。如某个方法调用,或者某个异常被抛出。
PointCut(切点):一系列连接点的集合,它指明处理方式(Advice)将在何时被触发,定义了Advice的应用时机。在Spring中,使用PointcutAdvisor将Pointcut与Advice结合成为一种对象,Spring内建的Pointcut都有对应的PointcutAdvisor;
packageorg.springframework.aop;
importorg.springframework.aop.Advice;
publicinterface Advisor{
boolean isPerInstance();
AdvicegetAdvice();
}
packageorg.springframework.aop;
publicinterface PointcutAdvisor extends Advisor{
PointcutgetPointcut();
}
PointcutAdvisor的几个实现类:
org.springframework.aop.support.DefaultPointcutAdvisor;
org.springframework.aop.support.NameMatchMethodPointcutAdvisor;
org.springframework.aop.support.RegExpMethodPointcutAdvisor;
org.springframework.aop.support.ControlFlowPointcut;用于判断在方法的执行堆栈中某个制定类的方法中,是否曾经要求目标对象执行某个动作。由于这是在执行时期才会确定是否介入Advices,因此是Spring提供的动态Pointcut功能。
Spring的Pointcut接口:
packageorg.springframework.aop;
publicinterface Pointcut {
ClassFilter getClassFilter();
MethodMatchergetMethodMatcher();
PointcutTRUE =TruePointcutINSTANCE;;
}
在需要使用交集、联集操作时,使用org.springframework.aop.support.Composablecut实现类。
Proxy(代理):代理有静态代理和动态代理两种方式,AOP使用的是动态代理方式。
几种Advice:Advice包括Aspect的真正逻辑,在java中具体来说即使一个类,由于织入至Targets的时机不同,可分为BeforeAdvice,AfterAdvice,AroundAdvice,ThrowAdvice。
packageorg.springframework.aop;
publicinterface MethodBeforeAdvice extends BeforeAdvice{
voidbefore(Method method ,Object[] args,Object target)throws Throwable;
}
publicinterface AfterReturningAdvice extends Advice{
voidafterReturning(Object returnValue ,Method m,Object[] args,Objecttarget)
throwsThrowable;
}
publicinterface MethodInterceptor{
voidinvoker( MethodInvocation methodInvocation ) throws Throwable;
}
packageorg.springframework.ThrowsAdvice接口只是一个标签式接口,没有定义任何方法。只要在方法中定义yourMethod([…],subclassOfThrowable); 只要subclassOfThrowable参数是Throwable的子类,在异常发生时便会检验设定的ThrowsAdvice是否符合异常类型的方法,如果有的话就通知它执行,以下是方法声明的例子: void afterThrowing([…],Throwablethrowable);应该注意的是不能在Advice中处理异常,应该在应用程序本身处理。
Introduction是一种特殊的Advice,在行为上来看,它不象Brfore、After、等Advice在方法前后介入服务,而是直接介入整个对象的行为,就好像增加了可操作的行为一样,为对象加入了原先没有的功能。在Spring中是通过org.springframework.aop.IntroductionInterceptor接口来实现Introduction的。该接口提供实现类org.springframework.aop.support.DelegatingIntroductionInterceptor实现了大部分细节,可以通过直接继承它并添加为目标对象增加的行为,并可以带有对象自己的状态。
Autoproxing:自动代理可以不需要对每一个目标对象手动定义代理对象,通过透过Bean的名称或是跟Piontcut的对比,自动为符合条件的目标对象建立代理对象:
org.springframework.aop.framework.autoproxy.BeanNameAutoCreator;
org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoCreator;
自动代理有是很方便,但同时也是有利有弊,因为时常会造成一些不清不楚的设定。
Spring-持久化的支持
Spring提供了对数据库持久层的支持,包括DAO框架和对其他ORM的整合封装,如整合封装了Hibernate,提供依循Spring一致的使用模型。并提供了编程式事务管理和声明式事务管理模式。结合SpringIoc容器与AOP框架的功能,可以简化数据库持久化的运用方式,并轻易地获得事务相关服务的功能。
DAO全名DataAccessObject,在应用程序中,DAO在进行数据的CUID中使得应用程序不依赖于特定的数据库实现,而是让它依赖一个接口,由特定的DAO支持对象来进行处理。在异常处理中,Spring不会抛出与数据库相关的异常,所有的异常都是org.springframework.dao.DataAccessException的子类,一个与数据库技术无关的异常,而且DataAccessException是RuntimeException的子类,也就是说它属于Unchecked异常,不必强制用try..catch处理。
DataSource注入:对于不同数据库的来源需求,Spring提供DataSource注入,更新数据来源只要在bean定义文件中修改配置。
org.springframework.jdbc.datasource.DriverManagerDataSource用来取得它的一个实例,通过driverClassName、url、username、password四个属性设定JDBC的驱动程序类、数据库URL协议等信息。由于DriverManagerDataSource没有提供连接池功能,并不适用于真正的大型项目中,因此可以使用DBCP(commons-dbcp.jar、commons-pool.jar、commons-collections.jar)以获得连接池功能。
org.springframework.jndi.JndiObjectFactoryBean 用来从JNDI获得DataSource。
用来简化JDBC的几个类:
1>.Org.springframework.jdbc.core.JdbcTemplate类,它被设计成线程安全,当中提供的一些操作方法封装了类似标准的jdbc流程(Connection的取得、Statement的建立、异常德处理、Connection/Statement的关闭等)。Spring对JDBC的封装等功能基本上可以独立于Spring来使用,除了JdbcTemplate之外,Spring还提供了其它的Template类,如Hibernate、JDO、iBatis等的Template实现。
2>.查询: 可以使用JdbcTemplate类的gueryForXXX()等方法;还可以实现
org.springframework.jdbc.core.RowCallbackHandler 接口,在查询数据之后先作一些处理再传回;
org.springframework.jdbc.core.RowMapper用来一次取回很多查询结果的对象;
还可以在查询中设定org.springframework.jdbc.core.RowMapperResultReader,它实现了
org.springframework.jdbc.core.ResultReader接口。
3>.执行: 可以使用JdbcTemplate类的execute()方法执行SQL称述;
4>.更新与插入:可以使用JdbcTemplate类的Update()方法,它有几个重载的版本,如:
org.springframework.jdbc.core.PreparedStatementCreator接口的对象以及和其互补的:
org.springframework.jdbc.core.PreparedStatementSetter接口。
以对象方式进行操作
使用Spring提供的org.springframework.jdbc.object包,可以用对象向导的方式来操纵数据库。
org.springframework.jdbc.object.RdbmsOperation抽象类,代表了RDBMS的查询、更新、预存程序等操作。它的子类org.springframework.jdbc.object.SqlUpdate和MappingSqlQuery等,被设计成为线程安全的实现。
org.springframework.jdbc.object.SqlFuncation用来执行sql语句。
对于主键,最好设置成为与业务逻辑无关,可以使用:
org.springframework.jdbc.support.inccrementer.DataFieldMaxValueIncrementer针对各数据库的版本如Oracle的OracleSequenceMaxValueIncrementer等..操纵它的nextValue()、nextLongValue和nextStringValue()来产生下一个主键值。
JDBC事务处理---Spring提供了两种事务管理方式:可编程的事务管理和声明式事务管理
Spring对JDBC事务进行了封装,通过抽象类:
org.springframework.transaction.PlatformTransactionManager接口进行实现,该接口存在许多实现类,使得在开发中能使用一致的编程模型,使用不同的事务管理技术:
DataSourceTransactionManager、HibernateTransactionManager、JdoTransactionManager和
JtaTransactionManager等。
TransactionDefinition接口的实例用于定义事务的(隔离级别、传播行为、超时,只读,异常)
可编程的事务管理: 可以通过直接使用各型PlatformTransactionManager或是使用
org.springframework.transaction.support.TransactionTemplate。
声明式事务管理: Spring的声明式事务管理依赖于它的AOP框架来完成,使用声明式事务管理的好处是事务的管理不入侵开发组件,事务属于系统层面的服务,而不是业务逻辑的一部分,如果需要更改事务管理策略的话,只是需要在配置文件中重新定义即可。
事务的属性(transactionAttributes):声明式事务管理以方法为单位,transactionAttributes自然就在于事务应用至方法上的策略,主要有以下几个参数:
1>.传播行为:
PROPAGATION_MANDATORY ―― 必须在一现成事务中运行,否则抛出异常;
PROPAGATION_NESTED ―― 必须在一嵌入得事务中运行或同PROPAGATION_REQUIRED
PROPAGATION_NEVER ―― 指定不能在事务中运行,否则抛出异常;
PROPAGATION_NOT_SUPPORTED ―― 指定不能在事务中运行,否则暂停现存事务;
PROPAGATION_REQUIRED ―― 支持现存事务,没有就新建一个;
PROPAGATION_REQUIRES_NEW ―― 新建一个事务,如有现存的就暂停它;
PROPAGATION_SUPPORT ―― 支持现在的事务,没有的话就以没事务方式执行。
2>.隔离级别(Drityread / Non-repeatable / Phantom read):
ISOLATION_DEFAULT ―― 使用底层数据库默认级别;
ISOLATION_READ_COMMITTED ――可读其他并行事务提交了的数据,可防止脏读;
ISOLATION_READ_UNCOMMITTED
――可读并行事务未提交了的数据,可能出现脏读、重读和虚读等问题;
ISOLATION_REPEATABLE_READ
――要求多次读取的数据必须相同,除非本身事务更新的数据,可避免脏读和重读;
ISOLATION_SERIALIZABLE――完整的隔离级别,锁住数据表格,可能有效率问题。
3>.只读提示:
必须搭配传播行为(PROPAGATION_NESTED、PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW)一起使用。
4>.超时指定:
与只读提示一样,必须搭配传播行为(PROPAGATION_NESTED、PROPAGATION_REQUIRED、
PROPAGATION_REQUIRES_NEW)一起使用。
通过org.springframework.transaction.interceptor.TransactionAttributeSource接口上的方法getTransactionAttribute()方法,可以传递事务的Mothod与class实例,在简单的设置中可以使用
TransactionProxyFactoryBean的transactionAttributes属性定义事务的(隔离级别、传播行为、超时,只读,-异常,+异常)。
使用TransactionProxyFactoryBean,指定介入的事务管理对象及其方法:
<bean id="userDAOProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
……
<propertyname="transactionManager">
<refbean="transactionManager"/>
</property>
<propertyname="transactionAttributes">
<props>
<propkey="insert*">PROPAGATION_REQUIRED,readOnly,-MyCheckedException</prop>
</props>
</property>
</bean>
transactionAttributes中的多个定义用”,”隔开,”-”/”+”表示出现异常是撤销/提交。
通过设置TransactionInterceptor可以管理更多细节:
<beanid="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
……
</bean>
在Spring中整合Hibernate
Spring整合了对Hibernate的设定,提供了org.springframework.orm.hibernate3.HibernateTemplate
等类,使得在使用Hibernate时可以简化程序的编写流程,并以与JDBC相类似的模型提供Hibernate编程式、声明式事务管理。
1>.SessionFactory注入:SessionFactory通常是一个单例,因而SessionFactory底层的DataSource可以使用Spring的Ioc注入,之后再将SessionFactory注入至相互依赖的对象中去。
……
<beanid="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<propertyname="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<propertyname="url">
<value>jdbc:mysql://localhost:3306/demo</value>
</property>
<propertyname="username">
<value>username</value>
</property>
<propertyname="password">
<value>password</value>
</property>
</bean>
<beanid="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<propertyname="dataSource">
<refbean="dataSource"/>
</property>
<propertyname="mappingResources">
<list>
<value>User.hbm.xml</value>
</list>
</property>
<propertyname="hibernateProperties">
<props>
<propkey="hibernate.dialect">
org.hibernate.dialect.Oracle9Dialect
</prop>
</props>
</property>
</bean>
…
2>.HibernateTemplate: 在实现Template-callback机制上Spring提供了一个类和一个接口:
org.springframework.orm.hibernate3.HibernateTemplate类
org.springframework.orm.hibernate3.HibernateCallback接口
在HibernateTemplate上也提供了多个便利的方法,在执行时自动建立HibernateCallback对象,如
get()、save()、delete()等方法。
还可以通过继承org.springframework.orm.hibernate3.support.HibernateDaoSupport类来使用DAO类,省去一些管理SessionFactory和HibernateTemplate的工作,只需注入SessionFactory即可。
3>.Hibernate事务管理
a>.编程式事务管理: 使用方法与JDBC类似,在JDBC中TransactionTemplate建立时需要实现一个
org.springframework.transaction.PlatformTransactionManager的实例,而在使用Hibernate时被换成了org.springframework.orm.hibernate3.HibernateTransactionManager实例。
b>.声明式事务管理: 使用方法也与JDBC类似,差别在于增加了transactionManager和userDAOProxy
……
<beanid="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<propertyname="sessionFactory">
<refbean="sessionFactory"/>
</property>
</bean>
<beanid="userDAOProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<propertyname="transactionManager">
<refbean="transactionManager"/>
</property>
<propertyname="proxyInterfaces">
<list>
……
其他服务:远程、邮件和计划任务
-
远程服务
1>.RMI: 在Spring中,可以透过org.SpringFrameWork.remoting.rmi.RmiServerExporter简化使用RMI编程,在需要在Bean定义文件中定义Bean,让Spring来进行管理、生成Bean的实例,这样既可以注册也可以启动RMI服务了。
Server端的编写:只需要告诉RmiServerExporter服务对象、名称与要代理的接口,之后Spring读取定义文件并生成Bean实例后,RMI服务便可以启动了。
Client的编写:只要透过org.SpringFrameWork.remoting.rmi.RmiProxyFactoryBean,并告知服务的URL、代理接口即可,在编写程序时就像在使用本地端管理的服务一样。
2>.Hessian && Burlap :
Hessian和Burlap都是轻量级的用于实现web服务的rpc协议,Hessian是将对象以使用中性的二进制通过http协议进行传送,而不用RMI,因此不受限于某种编程语言,而且二进制在传输是带宽需求较小。而Burlap则是将对象以XML文件格式通过http协议进行传送,XML的特点是有较高的可读解性,应用程序通过解析XML文件便可以获取精确的消息,同时也不受限于编程语言。
在Spring中使用Hessian和Burlap的方法相似,由于都是通过http协议进行传送,因此需要搭配SpringWeb框架(使用DispatcherServlet),在服务器端的web.xml中配置好DispatcherServlet。
配置与使用:首先需要导入Hessian(Burlap)API,如Hessian-2.1.12.jar或Burlap.jar,
在Server端使用org.SpringFrameWork.remoting.caucho.HessianserviceExporter或
org.SpringFrameWork.remoting.caucho.BurlapserviceExporter来发布服务;
Client端使用类同于使用RMI,只需要改写一下Bean的配置文件,并且换用:
org.SpringFrameWork.remoting.caucho.HessianProxyFactoryBean或
org.SpringFrameWork.remoting.caucho.BurlapProxyFactoryBean来配置Bean。
3>.HttpInvoker : 同样是使用是通过http协议进行传送,不同的时httpInvoler传送的是java序列化对象,用于使用了http协议,同样需要使用SpringWeb框架(使用DispatcherServlet),
在Server端使用org.SpringFrameWork.remoting.httpinvoker.HttpInvokerServiceExporter,
Client端使用org.SpringFrameWork.remoting.httpinvoker.HttpInvokerProxyFactoryBean来配置Bean。
-
邮件服务
邮件发送服务由Spring中的org.SpringFrameWork.mail.MailSender接口定义,通过两个实现类:
org.SpringFrameWork.mail.cos.CosMailSenderImpl对jasonHunter's COS(一个对servlet编程的工具库)进行支持;
org.SpringFrameWork.mail.javamail.JavaMailSenderImpl对javaMail进行支持。
可以使用org.SpringFrameWork.mail.javamail.MineMessageHepler来建立Http邮件,可以将MineMessageHepler的
setText()方法设置为true表示启用Http邮件;
setTo()方法设定收件人;
setFrom()方法设定发件人;
seSubject()方法设定主题;
……
addAttachment()方法用于为邮件增加附件。
-
任务计划服务
Spring对java.util.Timer和java.util.TimerTask类进行了抽象封装,可以通过Spring容器管理功能使用功能有限的Timer(只能指定任务和任务之间的周期,不能指定定点运行);而Spring另一个封装实现的Quarze(www.openmphony.com/qarzte)提供了更多的任务计划功能,在使用上更为方便。
1>.使用TimerTask
首先通过继承TimerTask建立一个一个任务计划,接着可以在Bean配置文件中使用org.SpringFrameWork.scheduling.timer.ScheduledTimerTask来指定任务的执行周期。定义好Bean的后要使用org.SpringFrameWork.scheduling.timer.ScheduledTimerTask来加入所有的计划任务,这样在Spring容器启动读取玩配置后便会自动开始运行所排好的任务了。
细化计划任务,不必继承TimerTask,而是可以通过Bean配置文件定义
org.SpringFrameWork.scheduling.timer.MethodInvokingTimerTaskFactoryBean来指定执行某个对象的具体某个方法。MethodInvokingTimerTaskFactoryBean在底层会自动建立TimerTask的实例以执行目标对象上被指定的方法。
2>.使用Quarze
可以通过继承org.SpringFrameWork.scheduling.quarze.QuarzeJobBean来实现一个Job类。接下来可以在Bean配置文件中使用:
org.SpringFrameWork.scheduling.quarze.SchedulerFactoryBean 排定Job,
org.SpringFrameWork.scheduling.quarze.SimpleTriggerBean 指定周期,
org.SpringFrameWork.scheduling.quarze.CronTriggerBean 的“CronExpression“属性用来
详细指定直接作用点(对多可以有7个时间元素)。
也可以不通过继承而是在Bean的配置文件中直接指定Job执行某个对象的方法,Spring为此提供了org.SpringFrameWork.scheduling.quarze.MethodInvokingJobDetailFactoryBean
主要是配置targetObject属性和targetMeethod属性。