关于spring的有关学习知识总结
2010-04-21 15:44
295 查看
1.spring是什么?
1)它是为属性赋值的一种工具(IOC||DI)
当希望一个类调用其它类的的方法时,
当在写一个vo时也经常为属性赋值。
2)它是用来处理系统级服务的一种工具(aop)
当程序的很多地方都需要同一个服务时,你该怎么办呢?方法调用,不管采用哪种方式,你的程序总要和被调用程序耦合到一起。为了解决这样问题,spring提出了自己的方案,什么样的解决方案以后再讲。
3)MVC框架(spring提供了自己MVC模式)
4)集成常用框架(hibernate,struts)
5)提供了JDBC和DAO的样板代码
6)轻量级的框架(整个jar包1M多一点,并且开支非常小)
7)非侵入性框架(spring开发出来的项目一般不依赖spring)
2.spring是如何为类的属性赋值的呢?
它是通过ApplicationContext实现的,那么这个类如何实现的呢,通过xml文件(applicationContext->实例化对象画图)。
3.实例
4.理解IOC(获得依赖对象的方式发生反转) 依赖注入(Dependency Injection) 容器
通过上面实例,在为属性赋值时,不是有由程序自己为属性赋值而是由spring的类ApplicationContext赋值,这种赋值方式有传统的方法改为spring方式,也就是说赋值的方式发生反转了。这就是反转控制(Inversion Of Control)
5.赋字符串及基本类型,类对象,内部bean,List或数组,Set,map,Properties,null
6.以上程序为属性赋值时,全是生成了get方法和set方法,也就是说spring在赋值时,通过set方法为属性赋值,spring不仅能通过set方法赋值还能通过构造方法为属性赋值。下面就讲一下,通过构造方法为属性赋值。
<constructor-arg>表示为构造方法传递一个参数值,
那么多参数的构造方法spring如何确定参数的顺序,知道我们可以通过index(从0开始)或通过type(类型的全路径)
6.构造与set方法的选择
使用set方法比较常用,简单,但是通过set方法赋值的对象不具有强制性,构造方法具有强制性,实例化之后的对象肯定能够使用。
7.自动赋值
需求:作为程序本身在配置文件中不想手动为属性赋值咋办呢?为此spring提供了四种自动赋值方法。byName(根据属性名到上下文中找相同的id),byType(根据属性类型到上下文中找相同的类型),constructor(根据提供的构造方法到上下文中找相同类型的值进行匹配),autodetect(试图先按constructor,如果不行再按byType)
default-autowire 默认认情况下不会自动装配
8.初始化方法和消毁方法
init destroy
需求:当spring根据property或构造方法赋完值,如果还需要更改对象里面的值或初始化值该怎么办呢?init
当spring容器(ApplicationContext)消毁bean时,我想释放掉一些资源,(连接对象)destroy
9.对Bean进行后处理器类
需求:对象实例化之后,如何做到对xml中的每一个类中的String类型的数据进行统一更改
在后处理器中,一定要返回更改之后的对象(干什么,为什么)
10.对bean工厂进行后处理(对ApplicaitonContext)
需求:在ApplicaitonContext加载完所有bean的定义信息之后,在实例化bean之前,想对ApplicaitonContext做一些后理工作,该怎么办呢(当配值文件中使用占位符时,可以替换成资源文件中的信息)
11.spring提供的bean工厂后处理器
需求:在为其它属性赋值时,它的值要来自于资源文件怎么办呢?
PropertyPlacehoderConfigurer(分散配值)
需求:在连接类中,如何做到为连接类的属性url,userName,password赋值呢,并且这些值来自于属性文件(.properties)?为了达到此目的,我们需要PropertyPlacehoderConfigurer类加载属性文件,然后再用占位符为url,password赋值。
13.属性编辑器
需求:如何把普通的字符串赋给一vo对象呢。为了解决这个问题,我们可以定义一个属性编辑器实现类型转换
继承PropertyEditorSuport(setAsText)
setValue()
为了告诉spring把字符串赋给vo对象,需要配置CustomEditorConfigurer(customEditors),实现类型到编辑器的映射。
14.获取国际化信息
需求:如何按照不同local显示不同的信息
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename">
<value>app</value>
</property>
</bean>
14.发布事件,监听事件
需求:在应用中,我们做注册用户信息时,如果用户已经存在的话,我们可以发布一个事件,告诉客户此用户已存在,用来做集中处理所有事件。
在创建事件类时,一定要继承ApplicationEvent.
在spring中,如何发布事件呢ctx.publishEvent();
如何接收发布过来的事件呢。实现ApplicationListener
15.在StuConnection类中,自己何知道类的id是什么呢?
实现BeanNameAware接口(bean名关注)(做日志)
在类中,如何做到ApplicationContext发布事件呢?
ApplicationContextAware(select)
16.单例bean 原型bean
17.总结:spring的作用是什么呢?它用来建立和存储类及类之间的关系(ApplicationContext,容器)。
18.Bean的生命周期(容器中的类可用之前所经过的过程)
实例化对象-->根据配置文件为属性赋值-->如果类实现BeanNameAware会调用setBeanName方法-->如果实现ApplicationContextAware会调用setApplicationContext-->如果实现BeanPostProcessor会调用postProcessBeforeInitialization()方法-->调用init方法-->调用后处理器的postProcessAfterInitialization方法
当容器闭时调用distroy方法.
二.面向切面(方面)编程(AOP)Aspect-Oriented Programming
1.spring是用来处理系统级服务的一种工具
系统级服务:当运行项目时,在控制台大家都能看到很多日志信息,这些日志功能在整个系统(项目)中到处使用。这个日志功能就是其中一种系统级服务。
那么spring是如何把系统级服务放到方法上的呢?看图
2.实例(为某个类运用方法前通知)
java.util.logging.Logger log=Logger.getAnonymousLogger();
log.info("运行开始.....");
方法后通知,周围通知(环绕通知)
3.总结几个概念
1)通知,切面,目标对象,代理对象,织入(编译期,类装载期,运行期),切入点,接入点(连接点)。
2)spring只支持方法连接点,代理对象是运行时创建的。
代理对象的创建有两种方式:proxy,cglib
3)spring把采用这种机制的方式称为面向切面(方面)编程
4)为一个类运用通知需要创建一个代理对象,那么为多个类运用通知,应该创建几个代理对象呢?
3.切入点(放置通知的条件)
需求:在我们把通知(系统服务)运用到StuModel上方法时,是为所有方法都运用了通知,那么,如果我想只给StuModel的save方法运用通知(系统服务)该怎么办呢?那么这个时候,我们就需要定义一个类,这个类专门用来告诉spring要为某个方法添加系统服务。那么这个类就叫切入点类(或者说在哪一点放置通知)。
那么如何定义一个切点类呢?为此spring提供了Pointcut接口,作为程序员,只需要实现这个接口就可以了。作示例实现Pointcut接口。
从实现类中发现我们还需要创建两个类,一个类是判断类是否符合添加通知的要求。另外一个类是告诉spring方法是否符合添加通知,只有两者都符合才能为我们的类添加通知。作示例实现ClassFilter和MethodMatcher接口。
4.advisor
需求:大家想想为了为StuModel运用通知,只有切入点行吗?很显然,还需要一个通知类。只有切入点和通知共同运用到我们的类上面,才会能为某个方法添加通知。所以现我们需要把切入点类和通知类合到一起创建一个类(实现PointcutAdvisor接口)--advisor类,示例
5.动态切入点
看一看切入点类,在类中一个isRuntime方法,如果这个方法返回true表示会调用具有三个参数的那个方法,在这个方法中我们可以根据调用方法时传过来的参数值来决定是否运用通知。这个切入点类就叫动态切入点。如果没有这么做的话就叫静态切入点.
6.大家知道手动创建advisor需要很多步,为了避免这样的麻烦spring为我们提供了一个静态的advisor类。NameMatchMethodPointcutAdvisor(advice,mappedNames)类,这个类能根据方法名来添加通知,示例
7.RegexpMethodPointcutAdvisor根据正规则表达式
8.创建引入
需求:如何为StuModel额外添加一个selectOne方法呢?
如果想达此目的,就需要学习引入通知
为了实现把selectOne方法添加到StuModel中,spring提供了DelegatingIntroductionInterceptor类,只要把需要的添加的方法通过接口(IOne)告诉它就行了,然后把这个类以通知的方式运用到proxy类上,别忘了让代理类实现IOne接口,示例
创建引入通知还有一种方法,实现IntroductionInterceptor接口,在此接口需要实现两个方法invoke,implementsInterface
有了通知它可以和advisor联合到一起(DefaultIntroductionAdvisor)
9.自动创建代理对象
需求:大家知道,如果想为你的类添加系统服务(通知)的话,就必须通过ProxyFactoryBean类创建代理对象才能实现,那么对象一个大型的项目可能要为很多类添加系统服务,如果这样,我们需要创建很多代理类对象,也是一件很麻烦的事情。那么,如何让spring自动创建代理呢,作为程序员不需要创建代理类对象呢?
为了达到这个目的,spring提供了BeanNameAutoProxyCreator类(interceptorNames,beanNames)。这个类能根据id名自动创建代理对象,并把系统服务添加到StuModel上。示例
三、spring操作数据库
1.spring编程理念
1)在进行方法调用时,通过接口来调用方法(通过接口来公开数据库访问类(DAO)中的所有方法)调用你操作数据的方法,体现松耦合.
2)在spring中,把操作数据库的model分成两部分:stuService和stuDao部分;service是专门用来处理业务部分,dao部分专门用来处理访问数据库部分;示例,创建IStuDao接口及实现类StuDaoImp,创建IStuService接口及实现类StuServiceImp
2.在操作数据库时使用模板(回调)和DAO支撑类操作数据库。
模板概念:大家知道,在用hibernate操作数据库时,写代码时,创建session和开启和关闭事务的步聚是总要重复写(不变部分),不同的地方只是save方法或select方法部分(可变部分)。为避免重复写不变部分,spring把这一部分创建成了模板类,为了把可变部分的内容给模板,spring采用接口回调把可变部分给模板。示例
DAO支撑类
四、spring的事务管理
1.事务需求:当进行转帐时,需要执行两sql语句,大家想想,如果这两条sql语句有其中一个失败行不行?那么如何做到一个失败,它们都失败呢,并且让它们的数据恢复至开始时的数据呢,或者要成功都成功呢?要想达到这个效果,那么们就必须把这两条sql语句放到事务当中去执行。
2.事务特点
原子性(automic),一致性(consistency),隔离性(isolation),持久性(durablity)
3.spring对事务的支持
为了让spring提供事务的支持,spring提供了事务管理器类,这几种事务管理器分别是
PlateFormMDataSourceTransactionManager-JDBC,HibernateTransactionManager-hibernate,JDOTransactionManager-jdo,PersistenceBrokerTransactionManager-OBJ,JTATransactionManager-JTA,这几个类都有事务的提交方法,事务的回滚方法。
注意:spring虽然提供了事务管理器,但其本身还是依赖低层技术实现事务管理的。
示例配置事务管理器
那么如何把事务管理器运用到stuService的save方法上呢;
1)程序中通过TransactionTamplate把save方法放到事务中去运行(示例),这也编程式事务
2)声明式事务:把事务管理器和事务属性当成通知,让代理类(TransactionProxyFactoryBean)把事务加到目标对象方法的周围。(示例:事务属性源先直接使用)
2)MatchAlwaysTransactionAttributeSource,它是用来设置事务属性,通过传播行为,隔离级别,只读属性,事务超时来表示事务属性,它有默认值(行为:PROPAGATION_REQUIRED,隔离级别:ISOLATION_DEFAULT)
在刚才的示例中,我们看到了设置事务属性源,它是用来设置事务的传播行为、隔离级别的。
3)事务属性:
它是用来表示如何或怎样把事务运用到方法。
可以通过如下设置来定义事务的属性:
1.传播行为:它定义了事务的边界
需求:
如何处理一个方法在两个事务中运行或是否运行在事务中,我们可以设置
它的取值都在TransactionDefinition中定义(PROPAGATION开头)
2.隔离级别
需求:
并发操作会带来一些问题:不可重复读,幻读,脏读为了避免这些并发问题,我们可以设置隔离级别:
都在TransactionDefinition中定义(ISOLATION开头)
3.只读属性
当设置了只读属性时,数据库会自动调整,来提高数据库的性能,注意:不能修改数据库和增加操作,删除操作
4.事务超时间隔
当一个事务占用的时间过长时,等其结束,不如让其回滚,以免一直占用资源(单位:秒)
5.通过DefaultTransactionAttribute更改事务属性
6.如何做到为不同的方法设置不同的事务属性呢?为此spring提供了NameMatchTransactionAttributeSource(
设置properties属性)。
7.事务捷径
通过设置TransactionProxyFactoryBean的transactionAttributes属性(方法名--事务属性)
8.修剪事务声明,在做声明式事务时,会创建多个代理对象,在创建多个代理对象时,事务属性和事务管理器出现重写代码,为此在创建事务代理对象时可以把公用代码创建成抽象代码,在创建代理对象时,直接从那继承就可以了,再补充上需要新加的代码。
三、远程调用
1.rmi(Remote method invoke)
1)公开远程方法
需求:银行付款服务中,经常会被其它系统的服务调用,所以,需要把银行付款服务公开为可以被其它系统访问的方法。
为了达到此目的spring提供了RmiServiceExporter,(StuService)在配置文件中,通过设置serviceName,service,serviceInterface,来公开service所指定类的方法。
2)访问远程方法
为了访问到远程公开的方法,spring提供了
RmiProxyFactoryBean代理类(serviceUrl,serviceInterface),通过此类可以代理远程的服务,访问代理对象就象访问远程方法一样方面。
2.Hessian和Burlap(基于xml)
介绍:Hessian服务是基于http协议访问的轻量级服务,它是通过二进制的方式来实现彼此交换信息,可以通过防火墙,自己的序列化机制。
1)公开Hessian服务(用HessianServiceExporter公开service,serviceInterface)
2)配置Hessian的访问路径(SimpleUrlHandlerMapping)
3)配
置DispatcherServlet(因为是基于http协议的所以要过servlet来访问Hessian)注意:spring的配置文件必须以servlet名称-servlet.xml为命名,同时要把xml文件放至web-inf中。
3.Http invoke
介绍:Http invoke服务是基于http协议远程服务,通过java的序列化机制,可以通过防火墙。
1)公开HttpInvoke服务(用HttpInvokeServiceExporter公开service)
2)配置HttpInvoke的访问路径(SimpleUrlHandlerMapping)
3)配置DispatcherServlet(因为是基于http协议的所以要过servlet来访问HttpInvoke)注意:spring的配置文件必须以servlet名称-servlet.xml为命名,同时要把xml文件放至web-inf中。
四、访问企业级服务
一)需求:在工作期间,每周向总经理发送邮件,这个需求在spring中该如何满足呢?
为此spring封装了java的Timer类,来实现定时的服务。
使用定时调用需要三个步骤
1.定义一个继承TimerTask类的任务类,在run方法中实现需要定时的任务,并配置它。
2.使用ScheduledTimerTask类为任务类设置调用周期。
timerTask,period
3.利用TimerFactoryBean启动任务。
scheduledTimerTasks(石英调度)
二)使用上面的定时器不能达到按照某个时间点来调用任务,为此spring提供了Quartz调度;
1.定义一个继承QuartzJobBean的Quartz任务,并通过JobDetailBean来配置它(jobClass,jobDataAsMap).
2.通过CronTriggerBean设置任务的运行时间(jobDetail,cronExpression:表达式为 秒 分 时 日 月 星期 年份,星期和日期冲突)。
3.利用SchedulerFactoryBean启动任务(triggers)
五.spring的MVC模式
1)spring的MVC模式是jsp+servlet+javabean的扩展(学生).
在spring中,如何做增加学生记录呢?请看图
示例
在spring中,组成MVC的组件主要有:jsp,Controller,SimpleUrlHandlerMapping,
InternalResourceViewResolver
2)在项目开发中,随着项目的增大,applicationContext.xml文件为扩大,为此要把内容分成几个部分,为达到此目的spring提供了ContextLoaderListener监听器类,此类能自动加载其它xml文件。
注意:在传参数时,参数名必须为contextConfigLocation。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/service.xml</param-value>
</context-param>
3)其它控制器类
1.AbstractCommandController
当你的控制器继承AbstractCommandController时,spring能够自动把jsp提交的值存到某个vo中(在构造方法中调用setCommandClass方法,把vo告诉spring)及可以做验证操作。
4)其它url映射器
六、整合
整合概念:在spring+hibernate整合的基础上,再加上struts,在和struts整合中,关键点是在Action类中访问ApplicationContext中的对象,为达到此目的spring提供了ContextLoaderPlugIn类(设置contextConfigLocation属性),此类是在struts-config.xml中配置的,通过此类就能把ApplicationContext对象加载到struts框架中。
为了在Action类中访问加载过来的ApplicationContext对象,spring提供了2种方式来访问ApplicationContext对象。
1)在Action类中继承ActionSupport,在execute方法中,通过getWebApplicationContext()方法得到WebApplicationContext。
2)在Action的配置文件中type的值为 spring的DelegatingActionProxy,然后,真正的Action类在spring的配置文件中配置,注意:用name不用id,name的值和path一样。
如果不想写代理Action类,可以通过一次配置DelegatingRequestProcessor
传播行为
PROPAGATION_MANDATORY
表示该方法必须运行在一个事务当中,如果当前事务不存在,将抛出一个异常
PROPAGATION_NESTED
表示如果当前已经存在一个事务,则该方法应当运行在一个嵌套的事务中,被嵌套的事务可以从当前事务中单独地提交或回滚,如果当前事务不存在,那么它看起来就和PROPAGATION_REQUIRED没有两样。请注意厂商对于这种传播行为的支持是参差不齐的,请参考资源管理的文档,确定它们是否支持嵌套的事务
PROPAGATION_NEVER
表示当前的方法不应该运行在 一个事务上下文中,如果当前存在一个事务,则会抛出一个异常。
PROPAGATION_NOT_SUPPORTED
表示该方法不应在事务中运行,如果一个现有的事务正在进行中,它将在该方法的运行期间被挂起。如果使用JTATransactionManager的话,需要访问TransactionManager.
PROPAGATION_REQUIRED
表示当前方法必须运行在一个事务中,如果一个现有的事务正在进行中,该方法将运行在这个事务中,否则的话,就要开始一个新的事务。
PROPAGATION_REQUIRES_NEW
表示当前方法必须运行它自己的事务里,它将启动一个新的事务。如果一个现有事务在运行的话,将在这个方法运行期间被挂起。
PROPAGATION_SUPPORTS
表示当前方法不需要事务处理环境,但如果有一个事务已经在运行的话,这个方法也可以在这个事务里运行。
隔离级别
ISOLATION_DEFAULT
使用后端数据库默认的隔离级别
ISOLATION_READ_UNCOMMITTED
允许你读取还未提交的改变了的数据,可能导致脏读、幻读或不可重复读。
ISOLATION_READ_COMMITTED
允许在并发事务已经提交后读取,可防止读取脏读但幻读或不可重复读仍可能发生。
ISOLATION_REPEATABLE_READ
对相同字段的多次读取的结果是一致的,除非数据被事务本身改变,可防止脏读、不可重复读,但幻读仍可能发生
。
ISOLATION_SERIALIZABLE
完全服从ACID的隔离级别,确保不发生脏读、不可重读。这在所有隔离级别中也是最慢的,因为它是典型的通过完全锁定在事务中涉及的数据表来完成的。
1)它是为属性赋值的一种工具(IOC||DI)
当希望一个类调用其它类的的方法时,
当在写一个vo时也经常为属性赋值。
2)它是用来处理系统级服务的一种工具(aop)
当程序的很多地方都需要同一个服务时,你该怎么办呢?方法调用,不管采用哪种方式,你的程序总要和被调用程序耦合到一起。为了解决这样问题,spring提出了自己的方案,什么样的解决方案以后再讲。
3)MVC框架(spring提供了自己MVC模式)
4)集成常用框架(hibernate,struts)
5)提供了JDBC和DAO的样板代码
6)轻量级的框架(整个jar包1M多一点,并且开支非常小)
7)非侵入性框架(spring开发出来的项目一般不依赖spring)
2.spring是如何为类的属性赋值的呢?
它是通过ApplicationContext实现的,那么这个类如何实现的呢,通过xml文件(applicationContext->实例化对象画图)。
3.实例
4.理解IOC(获得依赖对象的方式发生反转) 依赖注入(Dependency Injection) 容器
通过上面实例,在为属性赋值时,不是有由程序自己为属性赋值而是由spring的类ApplicationContext赋值,这种赋值方式有传统的方法改为spring方式,也就是说赋值的方式发生反转了。这就是反转控制(Inversion Of Control)
5.赋字符串及基本类型,类对象,内部bean,List或数组,Set,map,Properties,null
6.以上程序为属性赋值时,全是生成了get方法和set方法,也就是说spring在赋值时,通过set方法为属性赋值,spring不仅能通过set方法赋值还能通过构造方法为属性赋值。下面就讲一下,通过构造方法为属性赋值。
<constructor-arg>表示为构造方法传递一个参数值,
那么多参数的构造方法spring如何确定参数的顺序,知道我们可以通过index(从0开始)或通过type(类型的全路径)
6.构造与set方法的选择
使用set方法比较常用,简单,但是通过set方法赋值的对象不具有强制性,构造方法具有强制性,实例化之后的对象肯定能够使用。
7.自动赋值
需求:作为程序本身在配置文件中不想手动为属性赋值咋办呢?为此spring提供了四种自动赋值方法。byName(根据属性名到上下文中找相同的id),byType(根据属性类型到上下文中找相同的类型),constructor(根据提供的构造方法到上下文中找相同类型的值进行匹配),autodetect(试图先按constructor,如果不行再按byType)
default-autowire 默认认情况下不会自动装配
8.初始化方法和消毁方法
init destroy
需求:当spring根据property或构造方法赋完值,如果还需要更改对象里面的值或初始化值该怎么办呢?init
当spring容器(ApplicationContext)消毁bean时,我想释放掉一些资源,(连接对象)destroy
9.对Bean进行后处理器类
需求:对象实例化之后,如何做到对xml中的每一个类中的String类型的数据进行统一更改
在后处理器中,一定要返回更改之后的对象(干什么,为什么)
10.对bean工厂进行后处理(对ApplicaitonContext)
需求:在ApplicaitonContext加载完所有bean的定义信息之后,在实例化bean之前,想对ApplicaitonContext做一些后理工作,该怎么办呢(当配值文件中使用占位符时,可以替换成资源文件中的信息)
11.spring提供的bean工厂后处理器
需求:在为其它属性赋值时,它的值要来自于资源文件怎么办呢?
PropertyPlacehoderConfigurer(分散配值)
需求:在连接类中,如何做到为连接类的属性url,userName,password赋值呢,并且这些值来自于属性文件(.properties)?为了达到此目的,我们需要PropertyPlacehoderConfigurer类加载属性文件,然后再用占位符为url,password赋值。
13.属性编辑器
需求:如何把普通的字符串赋给一vo对象呢。为了解决这个问题,我们可以定义一个属性编辑器实现类型转换
继承PropertyEditorSuport(setAsText)
setValue()
为了告诉spring把字符串赋给vo对象,需要配置CustomEditorConfigurer(customEditors),实现类型到编辑器的映射。
14.获取国际化信息
需求:如何按照不同local显示不同的信息
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename">
<value>app</value>
</property>
</bean>
14.发布事件,监听事件
需求:在应用中,我们做注册用户信息时,如果用户已经存在的话,我们可以发布一个事件,告诉客户此用户已存在,用来做集中处理所有事件。
在创建事件类时,一定要继承ApplicationEvent.
在spring中,如何发布事件呢ctx.publishEvent();
如何接收发布过来的事件呢。实现ApplicationListener
15.在StuConnection类中,自己何知道类的id是什么呢?
实现BeanNameAware接口(bean名关注)(做日志)
在类中,如何做到ApplicationContext发布事件呢?
ApplicationContextAware(select)
16.单例bean 原型bean
17.总结:spring的作用是什么呢?它用来建立和存储类及类之间的关系(ApplicationContext,容器)。
18.Bean的生命周期(容器中的类可用之前所经过的过程)
实例化对象-->根据配置文件为属性赋值-->如果类实现BeanNameAware会调用setBeanName方法-->如果实现ApplicationContextAware会调用setApplicationContext-->如果实现BeanPostProcessor会调用postProcessBeforeInitialization()方法-->调用init方法-->调用后处理器的postProcessAfterInitialization方法
当容器闭时调用distroy方法.
二.面向切面(方面)编程(AOP)Aspect-Oriented Programming
1.spring是用来处理系统级服务的一种工具
系统级服务:当运行项目时,在控制台大家都能看到很多日志信息,这些日志功能在整个系统(项目)中到处使用。这个日志功能就是其中一种系统级服务。
那么spring是如何把系统级服务放到方法上的呢?看图
2.实例(为某个类运用方法前通知)
java.util.logging.Logger log=Logger.getAnonymousLogger();
log.info("运行开始.....");
方法后通知,周围通知(环绕通知)
3.总结几个概念
1)通知,切面,目标对象,代理对象,织入(编译期,类装载期,运行期),切入点,接入点(连接点)。
2)spring只支持方法连接点,代理对象是运行时创建的。
代理对象的创建有两种方式:proxy,cglib
3)spring把采用这种机制的方式称为面向切面(方面)编程
4)为一个类运用通知需要创建一个代理对象,那么为多个类运用通知,应该创建几个代理对象呢?
3.切入点(放置通知的条件)
需求:在我们把通知(系统服务)运用到StuModel上方法时,是为所有方法都运用了通知,那么,如果我想只给StuModel的save方法运用通知(系统服务)该怎么办呢?那么这个时候,我们就需要定义一个类,这个类专门用来告诉spring要为某个方法添加系统服务。那么这个类就叫切入点类(或者说在哪一点放置通知)。
那么如何定义一个切点类呢?为此spring提供了Pointcut接口,作为程序员,只需要实现这个接口就可以了。作示例实现Pointcut接口。
从实现类中发现我们还需要创建两个类,一个类是判断类是否符合添加通知的要求。另外一个类是告诉spring方法是否符合添加通知,只有两者都符合才能为我们的类添加通知。作示例实现ClassFilter和MethodMatcher接口。
4.advisor
需求:大家想想为了为StuModel运用通知,只有切入点行吗?很显然,还需要一个通知类。只有切入点和通知共同运用到我们的类上面,才会能为某个方法添加通知。所以现我们需要把切入点类和通知类合到一起创建一个类(实现PointcutAdvisor接口)--advisor类,示例
5.动态切入点
看一看切入点类,在类中一个isRuntime方法,如果这个方法返回true表示会调用具有三个参数的那个方法,在这个方法中我们可以根据调用方法时传过来的参数值来决定是否运用通知。这个切入点类就叫动态切入点。如果没有这么做的话就叫静态切入点.
6.大家知道手动创建advisor需要很多步,为了避免这样的麻烦spring为我们提供了一个静态的advisor类。NameMatchMethodPointcutAdvisor(advice,mappedNames)类,这个类能根据方法名来添加通知,示例
7.RegexpMethodPointcutAdvisor根据正规则表达式
8.创建引入
需求:如何为StuModel额外添加一个selectOne方法呢?
如果想达此目的,就需要学习引入通知
为了实现把selectOne方法添加到StuModel中,spring提供了DelegatingIntroductionInterceptor类,只要把需要的添加的方法通过接口(IOne)告诉它就行了,然后把这个类以通知的方式运用到proxy类上,别忘了让代理类实现IOne接口,示例
创建引入通知还有一种方法,实现IntroductionInterceptor接口,在此接口需要实现两个方法invoke,implementsInterface
有了通知它可以和advisor联合到一起(DefaultIntroductionAdvisor)
9.自动创建代理对象
需求:大家知道,如果想为你的类添加系统服务(通知)的话,就必须通过ProxyFactoryBean类创建代理对象才能实现,那么对象一个大型的项目可能要为很多类添加系统服务,如果这样,我们需要创建很多代理类对象,也是一件很麻烦的事情。那么,如何让spring自动创建代理呢,作为程序员不需要创建代理类对象呢?
为了达到这个目的,spring提供了BeanNameAutoProxyCreator类(interceptorNames,beanNames)。这个类能根据id名自动创建代理对象,并把系统服务添加到StuModel上。示例
三、spring操作数据库
1.spring编程理念
1)在进行方法调用时,通过接口来调用方法(通过接口来公开数据库访问类(DAO)中的所有方法)调用你操作数据的方法,体现松耦合.
2)在spring中,把操作数据库的model分成两部分:stuService和stuDao部分;service是专门用来处理业务部分,dao部分专门用来处理访问数据库部分;示例,创建IStuDao接口及实现类StuDaoImp,创建IStuService接口及实现类StuServiceImp
2.在操作数据库时使用模板(回调)和DAO支撑类操作数据库。
模板概念:大家知道,在用hibernate操作数据库时,写代码时,创建session和开启和关闭事务的步聚是总要重复写(不变部分),不同的地方只是save方法或select方法部分(可变部分)。为避免重复写不变部分,spring把这一部分创建成了模板类,为了把可变部分的内容给模板,spring采用接口回调把可变部分给模板。示例
DAO支撑类
四、spring的事务管理
1.事务需求:当进行转帐时,需要执行两sql语句,大家想想,如果这两条sql语句有其中一个失败行不行?那么如何做到一个失败,它们都失败呢,并且让它们的数据恢复至开始时的数据呢,或者要成功都成功呢?要想达到这个效果,那么们就必须把这两条sql语句放到事务当中去执行。
2.事务特点
原子性(automic),一致性(consistency),隔离性(isolation),持久性(durablity)
3.spring对事务的支持
为了让spring提供事务的支持,spring提供了事务管理器类,这几种事务管理器分别是
PlateFormMDataSourceTransactionManager-JDBC,HibernateTransactionManager-hibernate,JDOTransactionManager-jdo,PersistenceBrokerTransactionManager-OBJ,JTATransactionManager-JTA,这几个类都有事务的提交方法,事务的回滚方法。
注意:spring虽然提供了事务管理器,但其本身还是依赖低层技术实现事务管理的。
示例配置事务管理器
那么如何把事务管理器运用到stuService的save方法上呢;
1)程序中通过TransactionTamplate把save方法放到事务中去运行(示例),这也编程式事务
2)声明式事务:把事务管理器和事务属性当成通知,让代理类(TransactionProxyFactoryBean)把事务加到目标对象方法的周围。(示例:事务属性源先直接使用)
2)MatchAlwaysTransactionAttributeSource,它是用来设置事务属性,通过传播行为,隔离级别,只读属性,事务超时来表示事务属性,它有默认值(行为:PROPAGATION_REQUIRED,隔离级别:ISOLATION_DEFAULT)
在刚才的示例中,我们看到了设置事务属性源,它是用来设置事务的传播行为、隔离级别的。
3)事务属性:
它是用来表示如何或怎样把事务运用到方法。
可以通过如下设置来定义事务的属性:
1.传播行为:它定义了事务的边界
需求:
如何处理一个方法在两个事务中运行或是否运行在事务中,我们可以设置
它的取值都在TransactionDefinition中定义(PROPAGATION开头)
2.隔离级别
需求:
并发操作会带来一些问题:不可重复读,幻读,脏读为了避免这些并发问题,我们可以设置隔离级别:
都在TransactionDefinition中定义(ISOLATION开头)
3.只读属性
当设置了只读属性时,数据库会自动调整,来提高数据库的性能,注意:不能修改数据库和增加操作,删除操作
4.事务超时间隔
当一个事务占用的时间过长时,等其结束,不如让其回滚,以免一直占用资源(单位:秒)
5.通过DefaultTransactionAttribute更改事务属性
6.如何做到为不同的方法设置不同的事务属性呢?为此spring提供了NameMatchTransactionAttributeSource(
设置properties属性)。
7.事务捷径
通过设置TransactionProxyFactoryBean的transactionAttributes属性(方法名--事务属性)
8.修剪事务声明,在做声明式事务时,会创建多个代理对象,在创建多个代理对象时,事务属性和事务管理器出现重写代码,为此在创建事务代理对象时可以把公用代码创建成抽象代码,在创建代理对象时,直接从那继承就可以了,再补充上需要新加的代码。
三、远程调用
1.rmi(Remote method invoke)
1)公开远程方法
需求:银行付款服务中,经常会被其它系统的服务调用,所以,需要把银行付款服务公开为可以被其它系统访问的方法。
为了达到此目的spring提供了RmiServiceExporter,(StuService)在配置文件中,通过设置serviceName,service,serviceInterface,来公开service所指定类的方法。
2)访问远程方法
为了访问到远程公开的方法,spring提供了
RmiProxyFactoryBean代理类(serviceUrl,serviceInterface),通过此类可以代理远程的服务,访问代理对象就象访问远程方法一样方面。
2.Hessian和Burlap(基于xml)
介绍:Hessian服务是基于http协议访问的轻量级服务,它是通过二进制的方式来实现彼此交换信息,可以通过防火墙,自己的序列化机制。
1)公开Hessian服务(用HessianServiceExporter公开service,serviceInterface)
2)配置Hessian的访问路径(SimpleUrlHandlerMapping)
3)配
置DispatcherServlet(因为是基于http协议的所以要过servlet来访问Hessian)注意:spring的配置文件必须以servlet名称-servlet.xml为命名,同时要把xml文件放至web-inf中。
3.Http invoke
介绍:Http invoke服务是基于http协议远程服务,通过java的序列化机制,可以通过防火墙。
1)公开HttpInvoke服务(用HttpInvokeServiceExporter公开service)
2)配置HttpInvoke的访问路径(SimpleUrlHandlerMapping)
3)配置DispatcherServlet(因为是基于http协议的所以要过servlet来访问HttpInvoke)注意:spring的配置文件必须以servlet名称-servlet.xml为命名,同时要把xml文件放至web-inf中。
四、访问企业级服务
一)需求:在工作期间,每周向总经理发送邮件,这个需求在spring中该如何满足呢?
为此spring封装了java的Timer类,来实现定时的服务。
使用定时调用需要三个步骤
1.定义一个继承TimerTask类的任务类,在run方法中实现需要定时的任务,并配置它。
2.使用ScheduledTimerTask类为任务类设置调用周期。
timerTask,period
3.利用TimerFactoryBean启动任务。
scheduledTimerTasks(石英调度)
二)使用上面的定时器不能达到按照某个时间点来调用任务,为此spring提供了Quartz调度;
1.定义一个继承QuartzJobBean的Quartz任务,并通过JobDetailBean来配置它(jobClass,jobDataAsMap).
2.通过CronTriggerBean设置任务的运行时间(jobDetail,cronExpression:表达式为 秒 分 时 日 月 星期 年份,星期和日期冲突)。
3.利用SchedulerFactoryBean启动任务(triggers)
五.spring的MVC模式
1)spring的MVC模式是jsp+servlet+javabean的扩展(学生).
在spring中,如何做增加学生记录呢?请看图
示例
在spring中,组成MVC的组件主要有:jsp,Controller,SimpleUrlHandlerMapping,
InternalResourceViewResolver
2)在项目开发中,随着项目的增大,applicationContext.xml文件为扩大,为此要把内容分成几个部分,为达到此目的spring提供了ContextLoaderListener监听器类,此类能自动加载其它xml文件。
注意:在传参数时,参数名必须为contextConfigLocation。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/service.xml</param-value>
</context-param>
3)其它控制器类
1.AbstractCommandController
当你的控制器继承AbstractCommandController时,spring能够自动把jsp提交的值存到某个vo中(在构造方法中调用setCommandClass方法,把vo告诉spring)及可以做验证操作。
4)其它url映射器
六、整合
整合概念:在spring+hibernate整合的基础上,再加上struts,在和struts整合中,关键点是在Action类中访问ApplicationContext中的对象,为达到此目的spring提供了ContextLoaderPlugIn类(设置contextConfigLocation属性),此类是在struts-config.xml中配置的,通过此类就能把ApplicationContext对象加载到struts框架中。
为了在Action类中访问加载过来的ApplicationContext对象,spring提供了2种方式来访问ApplicationContext对象。
1)在Action类中继承ActionSupport,在execute方法中,通过getWebApplicationContext()方法得到WebApplicationContext。
2)在Action的配置文件中type的值为 spring的DelegatingActionProxy,然后,真正的Action类在spring的配置文件中配置,注意:用name不用id,name的值和path一样。
如果不想写代理Action类,可以通过一次配置DelegatingRequestProcessor
传播行为
PROPAGATION_MANDATORY
表示该方法必须运行在一个事务当中,如果当前事务不存在,将抛出一个异常
PROPAGATION_NESTED
表示如果当前已经存在一个事务,则该方法应当运行在一个嵌套的事务中,被嵌套的事务可以从当前事务中单独地提交或回滚,如果当前事务不存在,那么它看起来就和PROPAGATION_REQUIRED没有两样。请注意厂商对于这种传播行为的支持是参差不齐的,请参考资源管理的文档,确定它们是否支持嵌套的事务
PROPAGATION_NEVER
表示当前的方法不应该运行在 一个事务上下文中,如果当前存在一个事务,则会抛出一个异常。
PROPAGATION_NOT_SUPPORTED
表示该方法不应在事务中运行,如果一个现有的事务正在进行中,它将在该方法的运行期间被挂起。如果使用JTATransactionManager的话,需要访问TransactionManager.
PROPAGATION_REQUIRED
表示当前方法必须运行在一个事务中,如果一个现有的事务正在进行中,该方法将运行在这个事务中,否则的话,就要开始一个新的事务。
PROPAGATION_REQUIRES_NEW
表示当前方法必须运行它自己的事务里,它将启动一个新的事务。如果一个现有事务在运行的话,将在这个方法运行期间被挂起。
PROPAGATION_SUPPORTS
表示当前方法不需要事务处理环境,但如果有一个事务已经在运行的话,这个方法也可以在这个事务里运行。
隔离级别
ISOLATION_DEFAULT
使用后端数据库默认的隔离级别
ISOLATION_READ_UNCOMMITTED
允许你读取还未提交的改变了的数据,可能导致脏读、幻读或不可重复读。
ISOLATION_READ_COMMITTED
允许在并发事务已经提交后读取,可防止读取脏读但幻读或不可重复读仍可能发生。
ISOLATION_REPEATABLE_READ
对相同字段的多次读取的结果是一致的,除非数据被事务本身改变,可防止脏读、不可重复读,但幻读仍可能发生
。
ISOLATION_SERIALIZABLE
完全服从ACID的隔离级别,确保不发生脏读、不可重读。这在所有隔离级别中也是最慢的,因为它是典型的通过完全锁定在事务中涉及的数据表来完成的。
相关文章推荐
- 关于spring管理事务的学习总结。
- Spring学习总结(一)---谈谈对Spring IOC的理解(一:理论知识理解)
- 关于mybatis和spring结合的有关知识1--SQLsession生产的过程
- 黑马程序员_学习日记2_有关C#基础知识总结归纳之对象和类型
- spring学习总结(五)---Spring基础知识(二:Bean的配置项及其作用域)
- 怎样自学java新知识-学习spring整合jpa总结
- Hessian知识学习总结(三)——Spring + Hessian + Spring MVC
- Halcon PDF文档(hdevelop_users_guide)学习总结之三——关于变量窗口的小知识
- MySQL学习笔记_关于MySQL的字符类型VARCHAR长度知识总结
- MySQL学习笔记_关于MySQL的整数类型字段长度知识总结
- 关于需要学习的知识总结
- spring学习总结(三)---Spring基础知识(一)
- spring学习总结(四)---Spring基础知识(二:spring的注入方式)
- 【Spring】Spring Security 相关知识学习总结
- 关于算法学习的总结和感悟
- 学习Spring必学的Java基础知识(1)----反射
- Spring入门学习——第一阶段学习总结图
- 总结学习到得知识
- Java中关于String学习总结
- 我所学习的数据库知识总结!~