首页 > 代码库 > Spring
Spring
DI
一 Spring概述
1.什么是Spring?
⑴Spring是为了解决企业应用开发的复杂性而创建的,优秀的轻量级企业应用解决方案,开放源代码,主要特点是采用分层结构,允许单独使用某一模块,也可以将多个模块组合使用。
⑵企业应用:为了满足企业运行需要开发的软件系统,现在的企业应用大多运行在开放性平台(存在信息交互的可能性),不再是孤立的系统,而是在相互联系中构成了一个系统群。
⑶轻量级:轻量级框架如Struts、Spring,侧重于降低开发的复杂度,体积小,消耗小,相应地处理能力有所减弱。
⑷JavaBean:使用java语言编写的可重用组件,主要用作数据的载体。
⑸EJB:EnterpriseJavaBean,服务器端组件模型,定义了一个用于开发基于组件的企业应用的规范,本身复杂而繁琐。
2.Spring的优点:
⑴Spring采用分层结构,每一个模块可以单独使用,也可以联合使用。
3.Spring的技术基础:
⑴IoC:Injectionof Control,控制翻转。
⑵AOP:AspectOriented Program,面向切面编程。
4.Spring的构成:
⑴Springcore:Spring框架的核心,提供了Spring框架的基础功能,实现了IoC,包含重要的类BeanFactory。BeanFactory是IoC的容器,负责bean的实例化、初始化、使用与销毁。
⑵Springcontext:继承了BeanFactory,添加了许多功能,如国际化、数据校验等。
⑶SpringAOP:继承AOP的所用功能,通过事务可以将Spring管理的任意对象AOP化。
⑷SpringDAO:提供了JDBC的抽象层,简化了数据库厂商的异常错误,大幅度减少了代码,并且支持声明式事务与编程式事务。
⑸SpringORM;兼容所有流行的ORM框架,完美地整合了Hibernate。
⑹SpringWeb:提供了Servlet监听器上下文与Web上下文,集成了现有的Web框架,如JSP、Struts。
⑺SpringMVC:建立在Spring的核心功能之上,具有Spring框架的所有特性。
二几个比较重要的基础类
1.BeanFactory
一个接口,通过读取XML配置文件中javabean的定义,实现对javabean的创建、使用与管理。
2.XmlBeanFactory
BeanFactoy的一个实现类,通过流行的XML文件格式读取配置信息来加载javabean,具体加载过程:
Resource resource=newClassPathResource("xxxxx"); BeanFactory factory=newXmlBeanFactory(resource); Objectobj=(Object)factory.getBean("xxxx");
⑴其中Resource是一个接口,ClassPathResource是一个实现类,用于将资源封装成对象。
⑵classpath:代表类路径,因为程序执行最终使用是类文件,从类路径中加载,所以凡是程序运行必需的文件都要放在类路径中。Eclipse作为一种java集成开发工具,会将src目录下的文件自动放到类路径下。
3.ApplicationContext
一个接口,继承了BeanFactory,添加了许多功能,如国际化、数据验证等,有三个比较重要的实现类:
⑴ClassPathXmlApplicationContext:从类路径下加载配置文件,一般常用此类加载applicationContext.xml文件。
⑵FileSystemXmlApplicationContext:从指定路径加载文件,适用性范围广。
⑶WebApplicationContext:Spring与Web整合后在Web中的容器。
三依赖注入
1.IoC:控制反转
一种思想,依赖注入是该思想的一种事项,将创建实例的任务交给IoC容器,需要实例时向容器发送请求即可,这样降低了引用类A对被引用类B的依赖,即B发生改变,A需要修改很少一部分,甚至不需要修改。
2.IoC降低耦合度的实现过程
⑴在传统开发中,A类调用B类,就必须在内部创建B类,B b= new B(),当B类被删除,就需要修改A类的代码,这样A类就受到B类变化的拖累。而如果A类调用的是B类的接口,并且实例对象由外部创建,当外部实现类发生改变时,只要提供一个满足要求的实现类,A依然可以正常运行,不需要修改A中的代码,B的变化没有波及A。
⑵IoC降低耦合度是在对象创建过程实现的。
3.依赖注入
⑴IoC容器将A对象依赖的B对象注入到A中,叫做依赖注入。
⑵依赖注入的几种方式:
①setter注入:底层通过调用A中的setter方法将B注入。
配置文件的编写:
<bean id="引用变量"class="全限定性类名"> <property name="属性名"> <value>属性值</value> </property> </bean>
⑵构造器注入:底层通过调用构造方法将依赖注入。
配置文件的编写:
1 <bean id="引用变量"class="全限定性类名"> 2 <constructor-arg> 3 <value>参数值</value> 4 </constructor-arg> 5 </bean>
①使用构造器注入,配置文件中标签的赋值顺序必须与构造方法形参定义顺序一致,否则抛出出错。为了避免顺序不一致导致的错误,在配置文件中为每一个赋值标签设定一个index值,对应其要赋值的形参在构造器中的顺序:
1 <constructor-arg index="0"> 2 <value>参数值</value> 3 <constructor-arg>
②类中要有对应的构造方法。
⑶当属性为集合时在配置文件中设定初始值的方法为:
①数组与List集合:
1 <list> 2 <value>value01</value> 4 <value>value02</value> 5 </list>
数组还有一种更简单的赋值方式,值写在一块,用逗号隔开:
1 <property name=""value="value01,value02"/>
②Set集合:
1 <set> 2 <value>value01</value> 3 <value>value02</value> 4 </set>
③Map集合:
<map> 2 <entry key=""value=""/> 3 <entry key=""value=""/> 4 </map>
④Properties对象:
1 <props> 3 <prop key="xxx"></prop> 5 <prop key="xxx"></prop> 7 </props>
4.引用同一配置文件中其他的bean
<property name=""> <ref local="id"/> </property>
5.自动装配
⑴将一个bean调用的另一个bean自动转配到该bean中,通过<bean>标签的属性autowire实现。
⑵几种常用的自动装配方式
①byName:通过名称装配,将IoC容器中与属性名同名的bean注入。
配置文件编写:
<beanautowire="byName"id=""class=""/>
按名称装配的不足:如果IoC容器中存在多个同名而类型不同的bean,注入后就会发生错误。
②byType:将与属性相同的bean注入。
配置文件编写:
<beanautowire="byType"id=""class=""/>
按类型转配的不足:如果IoC容器中存在多个类型相同的bean,IoC容器会因为无法识别需要的bean而报错。
四内部bean
如果希望内部bean只能通过外部bean访问,那么将内部bean的定义放在外部bean内部:
<bean id="xxx"class="OuterClass"> <property name="innerClassAttrName"> <bean class="InnerClass">//因为不支持外部对象引用,所以不需要定义id <property name="">xxxxx</property> </bean> </property> </bean>
五同类抽象bean与异类抽象bean
1.产生的背景
在配置文件中,如果多个bean拥有共同的属性,分别为每一个bean配置这些共同的属性,数据冗余,为了消除冗余,将这些共同的属性提取出来,定义在一个抽象bean中,其他bean通过引用该抽象bean为属性赋值。抽象bean集中了共同属性,统一赋值。
2.同类抽象bean
⑴适用于为同类的bean赋值。
⑵配置文件编写:
<bean id="abstractBean"class="ClassA"abstract="true"> <property name=""value=""/> ........为共同属性赋值.......... </bean> <bean id="xxx"parent="abstractBean"> <property name=""value=""/> ........为特有属性赋值.......... </bean>
abstract="true":将该bean定义为抽象bean,以避免直接使用该bean,即定义为抽象以后,通过getBean无法访问该bean。
3.异类抽象bean:
⑴适用于为不同类型的bean赋值。、
⑵配置文件编写:
<bean id="abstractBean"abstract="true"> <property name=""value=""/> ........为共同属性赋值.......... </bean> <bean id="xxx"class=""parent="abstractBean"> <property name=""value=""/> ........为特有属性赋值.......... </bean>
六 bean作用域
1.bean:Spring中的bean就是由Spring创建、装配与管理的对象。
2.作用域的不同,bean的管理者与生命周期不同。
3.生命周期的设定
⑴第一种方式:<bean id=""class=""/>:采用默认值singleton。
⑵第二种方式:<bean id=""class=""singleton="true/false"/>。
⑶第三种方式:<bean id=""class=""scope="singleton/prototype"/>。
4.不同作用域介绍:
⑴singleton:bean采用单例模式,对bean的请求返回的是同一bean对象,生命周期与IoC容器相同,由IoC容器管理。
⑵prototype:采用多例模式,每一次请求获取的都是不同的bean对象,IoC容器将对象交给使用者,由使用者管理。
七 SpEL
1.Spring Expression Language,用于在配置文件中动态地为属性赋值,只赋值一次,该值可以来源于容器中其他bean的属性,调用bean方法的返回值,也可是调用容器以外其他类静态方法的返回值。
2.SpEL表达式只在初始化阶段为属性赋值,一旦初始化完成,表达式失效,即只是将beanA在配置文件的属性值传递给beanB的属性,并不是动态地保证beanB的属性值始终与beanA的属性值相同。这一点也可以从配置文件的功能来考虑,配置文件就是用来在初始化阶段为属性赋值,一旦初始化完毕,配置文件的任务就完成了,后续不再发挥作用。
3.基本语法格式:#{}。
4.调用容器中其他bean的属性:#{beanName.attrName}。
5.调用容器中bean的方法:#{beanId.method(arg)}。
6.调用容器以外其他类的静态方法:#{T(全限定性类名).method(arg)}。
7.在配置文件中的使用:<property name="xxxx"value="http://www.mamicode.com/#{xxxx}"/>,或者
<property name="xxxx"> <value>#{xxxx}</value> </property>
八 bean的生命周期
1.不同作用域的bean生命周期不同
⑴singleton:作用域范围singleton的bean生命周期与IoC容器的生命周期相同,容器初始化时创建,容器销毁时销毁。
⑵prototype:作用域范围prototype的bean由容器创建提交给请求方,生命周期由请求方负责。如果请求方不销毁,bean不会一直存在。
2.bean的生命周期可分为11个阶段,即总共有11时机可以用来改变bean。除自定义的BeanPostProcessor适用于所有bean而单独创建外,其他的都通过bean实现相应的接口实现,如BeanNameAware\BeanFactoryAware
\InitializingBean\DisposableBean等。
3.与生命周期相关的接口或者类
⑴在bean内部自定义控制生命周期的方法
①定义在setter方法执行完毕后调用的方法,即初始化完毕之后,该方法必须无参,在配置文件中配置:
<bean init-method="方法名">。
②定义在IoC容器关闭以后调用的方法,必须无参,在配置文件中配置<bean destory-method="方法名"/>
⑵BeanPostProcessor
①一个接口,其实现类只有在配置文件中配置之后才可以使用,由底层调用,配置时无需设定id。
②容器中所有的bean在初始化阶段都会调用其中的两个方法:
postProcessBeforeInitialization:在bean初始化完毕之前由容器调用;
postProcessAfterInitialization:在bean初始化完毕之后由容器调用。
九配置文件的分散编写
1.一个项目通常由一个团队的多个成员合作开发,如果在开发阶段共用一个配置文件,不仅降低了效率,而且不同的人共同操作,还容易发生错误,这是就需要允许多个配置文件的存在,而Spring正好提供了对多个配置文件的支持。
2.平等关系的配置文件:
⑴两个配置文件各自单独存在,不存在包含关系。
⑵在java代码中读取平等关系的配置文件需要使用指定类的可变参数的形式:
new ClassPathXmlApplicationContext(String...)
3.包含关系的配置文件:
⑴一个配置文件在形式上包含另一个配置文件,通过在配置文件中加入如下内容包含其他配置文件,读取该配置文件即可:
<import resources="classpath:xxxxx.xml"/>
①在配置文件路径前一定要加classpath,为底层指定加载方式,因为配置文件的加载方法有多种,以ClassPath开头的类从类路径加载,而以FileSystem开头的类从文件路径加载,在java中加载时使用ClassPath开头的类实际上已经设定了文件的加载方法。因为程序员只负责加载外层文件,内层文件的加载是由底层负责的,如果不指明加载方式,底层无法加载,底层执行过程大致是:提取classpath,然后进行判断,根据判断结果选择加载方式,如果classpath不存在,底层就无法进行判断,无法运行,就会抛出错误。
②classpath是一个单词,path的首字母不能大写。
十注解
1.注解是注册的一种,可以取代在配置文件中的配置。
2.注解的优点
在java源文件中直接注册,不需要编写配置文件,比较方便,而且标注在类中,可以清楚地看到注释与类的关系。
3.在配置文件头加入context约束,因为要使用<context>标签,只有该约束中有。
4.注解需要在配置文件中添加<context:component-scanbase-package="xxx"/>,注册扫描器,因为Spring不同于Hibernate与Struts,没有默认的配置文件,被动加载,必须显式指明配置文件,因此当采用注解开始时也必须显式
指明组件位置。
⑴如果包名为xxx,表示扫描该包及其子包;
⑵如果包名为xxx.*,表示只扫描子包。
5.常用注释:
⑴@Component(value="http://www.mamicode.com/相当于配置文件中的id"):表明该类是一个组件,扫描时容器会创建该类的实例,这是bean注解的第一步,先让容器把该类当做需要创建bean的类。
⑵@Scope(value="http://www.mamicode.com/singleton/prototype"):设置作用域。
⑶@Value(value=""):为一般属性赋值。
⑷@Resource(name=""):为域属性赋值。域属性就是自定义类的对象。@Autowired:Spring提供的域属性注入注解。
⑸@PostConstruct:在bean内部设定在初始化完成之后调用的方法。初始化完成的标识是InitializingBean实现类的方法afterPropertiesSet调用完毕。
⑹@PreDestroy:在bean内部设定bean销毁前调用的方法。
十一 SpringJUnit4
1.SpringJUnit4提供了对bean的简化测试方案,进行简单设置之后,测试bean时就不需要在创建容器,可以直接使用bean。
2.实现
⑴在类上加@RunWith(SpringJUnit4ClassRunner.class):表示采用SpringJUnit4进行测试。
⑵在类上加@ContextConfiguration(locations="classpath:xxxx.xml"):指明配置文件。
⑶在域属性加@Autowired:按照类型注入,也可以采用其他方式注入。因为并不是所有的域属性都是bean,有的可能是测试类新建的。
⑷然后在测试类方法中就可以直接使用bean了。
十二只有在对象由Spring容器创建时,属性与引用的其他的bean才会被注入对象中。在程序手动创建时,容器不会对对象施加任何作用。
AOP
一概述
1.Aspect Oriented Program,面向切面编程,一种编程思想,建立在动态代理机制之上。
2.产生背景
⑴在AOP产生以前,OOP是编程的基本原则,所有对象执行需要的代码都必须写在类中。如果多个类拥有一部分相同的代码,那么这些代码就必须在每个类中都编写,不仅代码大量重复,而且不便于维护,这时就产生了将那些重复出现、与业务无关的代码从业务中分离出来的思想,就是AOP。AOP将重复的、与业务无关的代码从业务中分离处理,业务执行时切入业务中,形式上与业务分离,执行时与业务结合,不仅便于维护,而且降低了业务逻辑部分与非业务逻辑部分的耦合度。
3.简单讲,AOP就是将无关且重复的部分从代码中分离处理,执行时再切入代码中。
4.重要的概念
⑴切面:对象执行过程中切入流程的、与业务逻辑无关的代码。与业务无关、重用度高的代码适合用作切面。在程序中,切面是一个集中了通知的类。
⑵切入点:切面切入流程的点,也是切面注入流程的点,Spring只支持方法类型的切入点,即切面只能在对象方法执行前后切入,不能切入方法内部。
⑶通知:切入点被横切时,所采取的业务逻辑,由通知确定执行那个切面。通知是切面中的方法。
⑷目标对象:切面切入的对象。
⑸织入:将切面功能应用于目标对象的过程。
⑹引用:动态地向目标对象添加属性与方法的过程。
二 Spring自身对AOP的实现
1.Spring自身提供了对AOP思想的实现,主要借助内置接口的实现类与配置文件完成。
2.重要的概念
⑴Advice:通知,切入点被横切时采取的处理逻辑,即在切入点前后执行的方法。在Spring中,Advice是一个层级比较高的接口,具体使用的通知都间接实现了该接口。缺点是,一旦定义就对所有方法都起作用。
⑵Advisor:顾问,Advice的装饰者,可以对方法进行筛选,使通知只对选定的方法起作用。常用到的两个实现类:
①NameMatchMethodPointcutAdvisor:列举选定的方法,使通知只对选定的方法有效。
②RegexMethodPointccutAdvisor:通过正则表达式匹配方法。
3.Advice
⑴前置通知:在切点执行前执行,实现MethodBeforeAdvice实现。
⑵后置通知:在切点成功执行后执行,排在环绕通知之后,方法无返回值不可以修改返回值,实现AfterReturningAdvice。
⑶环绕通知:在切点执行前与执行成功后执行,可以修改返回值,实现MethodInterceptor。
⑷异常通知:在切点抛出异常时,执行,实现ThrowsAdvice.
4.Advisor的配置
⑴Advisor是Advice的装饰者,可以为Advice指定方法,因此需要传入Advice与方法,将切点与目标方法绑定。
⑵采用NameMatchMethodPointcutAdvisor:
<bean id=""class="Advisor的两个实现类其中一个"> <property name="advice"ref="通知名"/>//装饰的通知 <property name="mappedNames"value="方法名"/>//即切点 </bean>
⑶采用RegexMethodPointcutAdvisor:
<property name="advice"ref="通知名" /> <property name="pattern" value="正则表达式,匹配对象时接口的方法" />
5.配置文件的编写
⑴代理通过ProxyFactoryBean类创建,底层执行Proxy.newProxyInstance(),对比底层实现,为该类属性赋值,动态地执行:
<bean id=""class="xxxxxx.ProxyFactoryBean"> <property name="targetName"name=""/> <property name="interceptorNames"value="通知名或顾问名"/> </bean>
6.基于顾问的自动代理生成器
⑴当有多个目标对象时,使用ProxyFactoryBean创建代理对象时,需要为每一个代理对象编写代理创建过程,而使用DefaultAdvisorProxyCreator,可以自动为目标对象创建代理。因为DefaultAutoProxyCreator底层实现了BeanPostProcessor,由底层自动调用。
⑵配置文件的编写:
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
⑶自动代理生成器只对Advisor有效,Advisor封装了方法,任何一个bean调用了该方法都会被增强。切面类型狭窄,目标对象广泛。
7.基于beanName的自动代理生成器
⑴该代理生成器弥补类基于顾问的代理生成器无法选择通知、无法选择目标对象的不足。
⑵配置文件的编写:
<bean id="proxy"class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames" value="target" />//选择要代理的对象 <property name="interceptorNames" value="methodInterceptor" />//选择切面 </bean>
8.无论是基于顾问的,还是基于beanName的自动代理生成器,都可以同时代理多个目标对象,为了区分被代理的目标对象只能通过目标对象来获取代理对象,这样才能保证一个代理对象指向一个目标对象。
三 AspectJ
1.AspectJ是一种独立于Spring框架的AOP思想实现,被Spring框架兼容,切面不需要实现特定的接口,就是普通的POJO类,比Spring提供的AOP更强大、灵活、边界,在实际开发中使用较普遍。
2.在AspectJ代理中,Spring容器充当代理工厂。
3.通过在配置文件中注册的方式实现AOP
<aop:configproxy-target-class="true/false"> <aop:aspect ref="切面所在类的id"> ---将切点定义在切面内,对其他切面不可见。也可以将切点定义在切面外,对所有切面可见--- <aop:pointcut ref="切点所在类的id" expression="execution(切入点表达式)"/> <aop:before method="方法名"pointcut-ref="切点id"/> <aop:after method="方法名"pointcut-ref="切点id"/> </aop:aspect> </aop:config>
⑴切入点表达式:
①什么是切入点表达式?
用于限制切入点的表达式,与表达式匹配的方法都可以用作切入点
②基本结构:[访问权限] 返回值类型 [全限定性类名] 方法名(..).
():匹配不带参数的方法。
(*):匹配带一个参数的方法。
(..):匹配带任意形式参数或则不带参数的方法。
③切入表达式的构成:
*:代表若干字符;
..:代表多级目录;
+:代表该类及其子类。
⑵<aop:config>:配置AOP的全部信息,包括切面、切点。proxy-target-class指明所用的代理机制,CGLIB,还是基于接口的代理JDK,默认为false,使用基于接口的代理。
⑶<aop:aspect>:配置切面,包含切点前执行的方法、切点后执行的方法、适用的切点等。
⑷<aop:pointcut>:定义切点,Spring只支持方法类型的切点,id属性为该切点指定一个id值,供他处引用,expression="execution(* 方法)"指明用作切点的方法,*必须有,之后跟一个空格。
⑸<aop:before>:指明在切点前执行的方法,pointcut-ref属性指明适用的切点。
⑹<aop:after>:指明在切点后执行的方法,无论切点是否成功执行都会执行,pointcut-ref属性指明适用的切点。
⑺<aop:after-throwing>:在抛出异常后执行。
⑻<aop:after-returningreturning="返回值result">:在返回值之后执行,返回值名必须与方法形参名相同。
⑼<aop:around>:紧贴代理对象方法前后执行,方法必须有返回值,可以修改目标方法的返回值。
①当使用环绕通知时,目标对象的方法只在环绕方法内部被调用后才可以执行,因为环绕通知底层采用MethodInterceptor,而拦截器内部必须显式地调用后面的方法,进程才能推进。
②目标对象的方法可能有返回值,因此环绕通知必须有返回值。
四 DAO
1.什么是DAO?
Data Access Object,数据访问对象,封装了一些对数据库进行持久化操作的方法,将持久化操作与一般的业务逻辑分开,便于维护与测试。封装了JDBC、简化了对数据库操作的接口。在实际开发DAO层由两部分构成,一部分是抽象DAO,一部分是其实现,DAO层提供了业务逻辑中可能用到的针对数据库的元操作,业务逻辑通过对DAO实现层方法的组合来操作数据库。
2.数据源
数据的来源,一般指数据库,又称数据连接池,一个数据源之所以成为数据的来源,最基本的是与数据库建立连接,数据库连接四要素。数据源是多用户访问情况下必须配置的,为了提交访问效率与速度。
⑴常用的数据源
①Spring提供的数据源DriverManagerDataSource,在实际开发中很少用到,常用到第三方数据源C3P0、DBCP。
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://localhost:3366/db_spring</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value>123</value> </property> </bean>
②C3P0数据源:
<bean id="c3p0"class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver" /> <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3366/db_spring"/> <property name="user" value="root" /> <property name="password" value="123" /> </bean>
③DPCP数据源:
<bean id="dbcp"class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://127.0.0.1:3366/db_spring"/> <property name="username" value="root" /> <property name="password" value="123" /> </bean>
3.Spring提供了一些抽象的DAO类:
⑴JdbcDaoSupport:支持以基础的JDBC技术操作数据库的抽象类,开发者需要设置数据源,通过子类获得JdbcTemplate来访问数据库。
①基本原理:利用框架提供的类DriverManagerDataSource创建与数据的连接,然后通过该类的实例获得Connection对象,后续操作同JDBC相同。Dao层实现继承JdbcDaoSupport,内部获取getJdbcTemplate进行底层数据库操作。
②利用JdbcDaoSupport访问数据库的实现:
Dao的实现层继承JdbcDaoSupport,getJdbcTemplate获取模板对象,通过模板对象封装的方法操作数据库:
update:在模板中增删改统一用updae方法,几种重载形式:
update(sql,arg):其中arg是可变长度参数,用来为sql语句中占位符赋值。为了安全与复用,sql与hql均采用参数绑定机制。
queryForObject(slq,requiredClass,arg):用于查询一个字段,并且查询结果唯一。requeredClass表示查询字段的类型,以便对查询结果转型。
queryForList(slq,requiredClass,arg):用于查询一个字段,结果可能有多个。
queryForObject(sql,rowMapper,arg):查询结果是一个对象,其中rowMapper用于将查询字段封装成一个对象,查询结果必须包含对象的全部属性。
query(sql,rowMapper,arg):返回对个对象。
③数据源注入时自动创建模板,所以不需要在Dao的实现层显式注入JdbcTemplate的,即注入数据源时自动创建模板。
④系统自动在方法结束时销毁JdbcTemplate对象,因此每次在方法中使用时都需要重新创建。
⑤HibernateDaoSupport:支持在Hibernate中操作数据库的抽象类,开发者需要设置SessionFactory,然后获得Hibernate的实现,HibernatDaoSupport底层实现复杂,效率低,不建议使用。
4.JdbcDaoSupport/HibernateDaoSupport层级都高于对应的模板类,内部都提供了获取相应模板类的方法,与数库的交互通过模板类来完成。应用Spring提供的DAO模块时,自定义类通常继承XXXDaoSupport类,在自定义方法内部
获得响应模板类来具体操作数据库。
5.在实际开发中,先定义一个抽象DAO层,再创建一个实现层,抽象DAO层增删改查方法的名称与JDBC底层操作名称一致,服务层即具体利用DAO实现层进行数据库操作的层中,增删改查方法的名称与DAO层对应名称区分开。
五事务概述
1.Spring事务管理是基于AOP实现的,而Spring的AOP是以方法为单位的,所以Spring的事务属性就是对事务应用到方法上的策略。Spring的事务管理是利用AOP技术在DAO核心代码前后切入事务管理代码实现的。
2.Spring提供了PlatformTransactionManager接口来管理事务,该类提供了用于事务管理的通知,可以将该类视作切面,两个重要的实现类,不同的访问数据库的方式采用的实现类不同:
⑴DataSourceTransactionManager:适用于JDBC、Mybatis。
②HibernateTransactionManager:适用于Hibernate。
⑶事务管理器的核心操作是对事务的回滚与提交,而进行回滚或者提交时都需要建立与数据库的连接,因此需要把数据源传入事务管理器中。
3.Spring在默认情况下,发生运行时异常回滚,编译时异常提交。程序员可以改变回滚方式。
4.事务的四大属性分为传播行为、隔离级别、只读和超时。
⑴事务的传播行为用于确定是否将事务应用在方法上以及应用的策略,比如应用当前事务,新建事务。
5.Spring框架提供了两种对AOP思想的实现:一种是Spring自身的实现,另一种是兼容的AspectJ的实现,由于Spring的事务管理是基于AOP的,所以与AOP实现相对应,事务管理也有两种类型。
6.Spring事务管理的基本构成:代理工厂、目标对象、切点、切面、事务属性。
六基于Spring AOP的事务管理
1.在Spring AOP构成的四个要素:代理工厂、目标对象、切点、切面。
⑴代理工厂:在SpringAOP事务管理中采用TransactionProxyFactoryBean充当代理工厂。
⑵切面:在Spring事务管理中PlatformTransactionManager充当切面。
2.配置文件的编写:
<bean id=""class="xxxTransactionProxyFactoryBean">//代理工厂 <property name="target" ref=""/>//目标对象 <property name="transactionManager"ref=""/>//切面 //事务属性,就是事务应用到目标对象方法上的策略 <property name="transactionAttributes> <props> <prop key="目标对象方法">事务四大属性</prop> </props> </property> </bean>
3.为什么规定事务的属性?
因为目标对象中有多个方法,并不是所有方法都需要被事务管理,被事务管理的方法所需要的管理方式也不同,因此需要通过事务属性进行个性化定制,如ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-Exception。
4.Spring事务管理默认在发生编译时异常时提交,也可以设置成发生编译时异常回滚,在事务属性中设置:"-Excpetion",以负号开头,加异常,标识当发生该异常时事务回滚。
七基于AspectJ的事务管理
1.配置文件的编写:
<tx:advice id="advice"tansaction-manager="transactionManger"> <tx:attributes> <tx:method name="buyStock" isolation="DEFAULT"propagation="REQUIRED"rollback-for="StockProcessException" /> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="p01"expression="execution(xxxx)"/> <aop:advisoradvice-ref="advice"pointcut-ref="p01"/> </aop:config>
八注解
1.以上两种事务管理是基于配置文件实现的,缺点是需要为每一个代理对象创建代理工厂,因此提供了基于注解的实现,可以方便地为多个对象创建代理:
⑴在配置文件中添加:<tx:annotation-driventransaction-manager="transactionManager"/>,指明事务管理器。
⑵在目标对象方法上添加以下注解,设定事务的属性:
@Transactional(isolation =Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor=StockProcessException.class)
Spring