Spring笔记







 

spring简介【了解】

  1.Spring是一个基于Java的轻量级的J2EE框架

    基于Java: 底层Java实现

    轻量级:性能较高,运行速度较快,内存消耗较少

    重量级组件:EJBCGI

   J2EE应用框架:Spring可以在JEE开发的三层架构的每一层为开发者带来帮助

    表现层:Servlet/JSPStruts2SpringMVC

    业务层:Bean管理、AOP、事务管理

    数据层:JDBCHibernateSpring JDBCTemplate

    域模型层:实体类+DAO

    服务层:远端调用(webservice[类似技术RMI+JNDI]

  Spring提供的每层的服务技术

    表现层:String MVC

    业务逻辑层:Bean管理、AOP、事务管理

    数据层:DAO支持抽象类,DAO模板技术JDBCTemplate

  2. Spring的发展历程

    创始人:Rod Johnson

    Expert One-to-One J2EE Design and Development(2002)

    阐述了J2EE使用EJB开发设计的优点及解决方案

    Expert One-to-One J2EE Development without EJB(2004)

    阐述了J2EE开发过程中不使用EJB的解决方式(Spring雏形)

  3.Spring核心技术

 

  IOC:控制反转

  AOP:面向切面编程/面向方面编程

4.Spring是一个超级的“黏合平台”,将很多技术黏合在一起,形成一个整体,使每个组件发挥其最大功效

资源包整理【了解】【应用】

  1.本课程基于Spring3.2.0进行讲解

    2.下载地址:http://maven.springframework.org/release/org/springframework/spring/

    说明:通过Maven部署资源从仓库获取(后期课程)

  3.资源文件

    Spring资源包下 spring-framework-3.2.0.RELEASE-dist.zip

    Spring依赖资源包 spring-framework-3.0.2.RELEASE-dependencies.zip

  4.资源包目录层次结构

    docs:API帮助文档与官方手册

    libs:开发使用的jar

    schema:开发使用的XML约束文档源文件

  5.开发jar

    核心jar(4)

    spring-beans-3.2.0.RELEASE.jar

    spring-context-3.2.0.RELEASE.jar

    spring-core-3.2.0.RELEASE.jar

    spring-expression-3.2.0.RELEASE.jar

    日志相关jar(2)

    commons-logging-1.1.1.jar

    commons-logging日志整合,与slf4j类似,由apache提供

    log4j-1.2.15.jar

IoC【理解】【应用】【重点】

  1.IoC(Inversion of Control)控制反转

    A:控制:控制的双方是什么?谁控制谁?

    主控方:Spring

    被控方:应用程序所使用的资源

    (原始)应用程序控制自己执行操作需要使用的外部资源

    (Spring)Spring控制整个程序中所需要使用的外部资源

    B.反转:什么是反转?反转什么?

    正向:应用程序直接调用资源

    反向:应用程序依赖Spring为其提供资源

    反转的是资源的控制权

    应用程序由主动调用资源,变为被动的等待Spring提供资源

    C.有什么好处?

    正向缺点:应用程序控制的资源分布在程序的每一个地方

    反向的优点:所有的资源都在Spring中,便于管理

    总结:Spring反向控制应用程序所需要使用的外部资源。资源受Spring管理,利用率最大化。

  2.Spring模型演化过程

    A.基于分层设计

      UserAction 使用UserService,new UserService()

      UserService 使用UserDAO,new UserDAO()

      UserDAO

    B.工厂模式,使用面向接口编程设计,解决层与层之间的紧耦合

      制作接口,制作实现类,制作对象工厂

    C.工厂模式+配置

      制作XML文件,将实现类配置到XML文件中

      读取XML文件中的配置信息,得到实现类的类名

      使用反射思想,获取实现类对象 class.newInstance();

    D.Spring设计雏形 自动的工厂+配置

      工厂由Spring提供,实现类使用XML格式配置

  3.IoC基础实例

    A.导入jar(6)

    B.制作log4j对应的配置文件

    C.src目录下创建核心配置文件applicationContext.xml

    说明:格式可以从xsd-config.html获取

复制代码
<?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.xsd
">
</beans>
复制代码

   D.将应用程序需要使用的资源配置成SpringBean

    <!-- Spring管理的资源全部声明到配置文件中 -->

    <!-- 所有资源以Bean的形式存在 -->

    <!-- bean:声明一个资源Bean -->

    <!-- bean:id:用于区分bean的标识 -->

    <!-- bean:class:bean对应的模型类名 -->

    <bean id="userDao" class="cn.itcast.spring.ioc.UserDao"> </bean>

  E.创建ApplicationContext对象

    ApplicationContext ctx = new ClassPathXmlApplicationContext("配置文件名");

    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

  F.获取Bean对象

    使用应用上下文对象获取

    ctx.getBean("beanid属性值");

    ctx.getBean("userService");

    补充:使用文件系统获取配置信息,要求配置文件在工程路径下(少用)

    ApplicationContext ctx = new FileSystemXmlApplicationContext("applicationContext.xml");

DI【理解】【应用】【重点】

1.DI(Dependency Injection)依赖注入指应用程序依赖Spring为其提供运行时所需的资源

2.DI实例

  A.在应用程序中声明要使用的资源

    private String msg;

  B.为其提供setter访问器

    public void setMsg(String msg) {

      this.msg = msg;

    }

  C. Bean配置中配置该资源对象具有某个属性,属性可以配置多个

    <bean id="userService" class="cn.itcast.ioc.helloworld.UserService">
      <!-- 在配置中,为该Bean需要注入的资源进行初始化 -->
      <!-- property:为该Bean注入属性 -->
      <!-- property:name:注入的属性名称(变量名) -->
      <property name="msg" value="itcast"/>
    </bean>

 注意:当配置中出现的属性在Bean类中不存在时,抛出异常

3.IoCDI区别

  同一件事,站在不同角度上看待问题的不同描述

  IoC:Spring立场

  DI:应用程序立场

BeanFactory【了解】(实际开发中,优先选择ApplicationContext对象,避免使用BeanFactory)

1.BeanFactoryApplicationContext的顶层父接口,使用BeanFactory接口也可以完成获取Bean的操作

2.操作步骤:

  A.初始化Resource对象

    Resource res = new ClassPathResource("applicationContext.xml");

  B.初始化BeanFactory对象

    BeanFactory bf = new XmlBeanFactory(res);

  C.根据id名称获取Bean

    UserService service = (UserService) bf.getBean("userService");

3.AppplicationContextBeanFactory的区别

  A.加载方式不同

    AppplicationContext:立即加载,加载配置文件时即加载

    BeanFactory:延迟加载,获取Bean实例时才加载

  B.AppplicationContext具有更多的功能

    国际化处理

    事件传递

    Bean自动装配

    各种不同应用层的Context实现

  注意:实际开发中,优先选择ApplicationContext对象,避免使用BeanFactory

4.Schema风格离线约束配置方式

  A.拷贝访问路径

  B.打开MyEclipse设置中的XML catalog选项

  C.创建新的映射

  D.选择对应的schema风格的约束文件

  E.key type修改为schema location

  F.将要配置的路径复制到key

Bean配置(XML【理解】【应用】【重点】

1.Bean对象初始化方式有三种

  构造器初始化:

    Bean对应的类必须提供一个默认无参可访问的构造方法

  静态工厂初始化【了解】

    提供一个工厂类,使用其中的静态方法获取对象

<bean id="userService2"
class="cn.itcast.bean.UserStataicFactory"    配置中所配置的class配置成工厂类的类名
factory-method="getInst"    配置工厂类中的创建实例的静态方法
>
</bean>

  实例工厂初始化【了解】

    提供一个实例工厂类,使用其中的实例方法获取对象。由于该工厂类本身需要创建对象,因此该对象必须受Spring控制,所以必须配置该工厂类为Bean   

复制代码
<!—实例化工厂Bean -->
<bean id="uf" class="cn.itcast.bean.UserFactory"></bean>
<!--使用实例工厂创建Bean -->
<!--factory-bean: 配置实例工厂在Spring范围内对应的Bean的id名称-->
<!--factory-method:配置工厂类中的创建实例的实例方法-->
<bean id="userService3"  factory-bean="uf"  factory-method="getInst2"></bean>
复制代码

2.Bean的作用域

  Spring初始化的Bean默认为单例模式,如果想修改成非单例模式需要修改Bean的作用范围

  <bean id=”beanId” class=”BeanClassName” scope=prototype></bean>

  scope属性:

  singleton:单例

  prototype:非单例

  request:请求对象范围request.setAttribute("beanId",obj);

  session:会话Session范围request.getSession().setAttribute("beanId",obj);

  globalSession:全局会话

    分布式服务器

3.Bean的生命周期

  定义Bean初始化与销毁时的动作,属于回调方法配置

  定义bean时指定两个回调方法,控制bean的初始化与销毁操作时执行的动作

  <!-- init-method:初始化回调方法名,配置的方法必须由bean对象提供-->
  <!-- destroy-method:销毁回调方法名,配置的方法必须由bean对象提供-->
  <bean id="user" class="cn.itcast.lifecycle.User" 
      init-method="init" destroy-method="destroy" scope="prototype">
</
bean>

   销毁操作只针对scope="singletion"的对象,对于非单例对象无效

  单例对象的销毁是在IoC容器关闭时发生,使用ClassPathXmlApplicationContext对象close方法完成

  非单例Bean对象的内存回收交由JVM完成——GC

4.Bean属性注入

  注入方式有两种

  构造器注入【了解】

    A.提供对应的构造方法

    B.配置中设置构造方法的参数

复制代码
<!-- constructor-arg:使用构造器传递参数  -->
<!-- value:赋值 -->
<bean id="bean6" class="cn.itcast.bean.xml.Bean6">
   <constructor-arg value="传智播客"/>
   <constructor-arg value="2014"/>
</bean>
复制代码

注意:如果类型匹配不成功,可以为配置中指定index索引属性,对应构造器中参数的位置

<bean id="bean6" class="cn.itcast.bean.xml.Bean6">
  <constructor-arg index="0" value="2014" type="java.lang.Integer"></constructor-arg>
  <constructor-arg index="1" value="itcast" type="java.lang.String"></constructor-arg>
</bean>

说明:构造器传参受构造器参数位置和类型的限定,因此不常使用

Setter注入【重点】

前提:setter注入要求Bean必须提供无参可访问构造方法

注入简单类型:String,基本数据类型封装类

A.提供对应要注入的属性

B.为每个要注入的属性提供对应的标准封装setter方法

C.在配置中为Bean指定要注入的属性,使用property元素 name=“属性名” value=”值”

<property name="属性名" value="值"/>

注入引用类型:对象

A.为某个Bean注入引用类型的值,首先在Bean对应的类中声明对应的属性

  private TeacherDAO dao;

B.为每个要注入的属性提供对应的标准封装setter方法 (访问器)

  public void setDao(TeacherDAO dao) {
    this.dao = dao;
  }

C.必须保障引入的对象是Spring控制的Bean

  <!-- 声明引用类型的资源为Bean -->
  <bean id="teacherDao" class="cn.itcast.di.setter.TeacherDAO"></bean>

D.Bean的属性注入中,使用ref引用对应的资源 ref=”beanId/beanName”

复制代码
<!-- setter注入 -->
<!-- name:属性名 -->
<!-- value:简单类型的值 -->
<!-- ref:引用别的Bean,beanId/beanName -->
<bean id="bean7" class="cn.itcast.bean.xml.Bean7">
  <property name="name" value="itcast"/>
  <property name="age" value="8"/>
  <property name="dao" ref="teacherDao"></property>
</bean>
复制代码

5.P命名空间的使用【了解】

Spring2.5提供了一种简化配置格式,P命名空间支持

A. xml头信息中引入对p命名空间的支持

  xmlns:p="http://www.springframework.org/schema/p"

B. 将所有的属性注入property子元素全部修改为bean的属性

原始格式:

<bean>
  <property name="propName" value="propValue"/>
  <property name="propName" ref="beanId"/>
</bean>

p空间格式:

<bean  
p:propName="propValue"      //注入简单类型
p:propName-ref="beanId"    //注入引用类型
>
</bean>

6. SpEl【了解】

  Spring3.0引入全新的SpEL(Spring Expression Language)Spring表达式语言,支持各种格式语法格式,所有的属性注入全部使用value属性名

  详情参考《Spring_表达式语言.pdf

7.集合注入【了解】

  Spring支持为Bean注入集合

List

复制代码
<property name="list">
     <list>
       <value>Java</value>
       <value>Struts2</value>
       <value>Spring3</value>
     </list>
</property>
复制代码

Set

复制代码
<property name="setCol">
     <set>
       <value>张三</value>
       <value>张大三</value>
       <value>张小三</value>
     </set>
</property>
复制代码

Map

复制代码
<property name="map">
     <map>
       <entry>
         <key>
           <value>张三</value>
         </key>
         <value>中国</value>
       </entry>
       <entry>
         <key>
           <value>约翰</value>
         </key>
         <value>中国</value>
       </entry>
       <entry>
         <key>
           <value>吴莫愁</value>
         </key>
         <value>榜单No.1</value>
       </entry>
       <entry key="小沈阳" value="榜单No.3"></entry>
     </map>
</property>
复制代码

Properties

复制代码
<property name="props">
     <props>
       <prop key="BIDU">百度</prop>
       <prop key="SINA">新浪</prop>
       <prop key="NQ">网秦</prop>
     </props>
</property>
复制代码

 团队开发【了解】【操作】

1.团队开发时,每个独立的模块制作成一个独立的配置文件

  命名格式:applicationContext-模块名.xml   模块名使用全小写字母

2.某个配置文件中,使用其他配置文件中的Bean,导入对应的配置文件

  <import resource="applicationContext.xml"/>

3.Bean的冲突问题

  A.当多个配置中具有相同idBean时,后加载的替换先加载的(由配置文件的加载顺序决定)

  B.当多个配置中具有相同idBean时,import导入相当于拷贝(由配置文件的Bean定义顺序决定)

  C.同一个配置文件中id不能重复,不同配置文件,同id依赖上述规则相互覆盖

4.id名称比较复杂,或者定义名称过长时,可以为bean追加别名,使用name属性完成

  name=”aa,bb,cc”

5.同一个工程中,仅配置一个主配置文件applicationContext.xml,其中添加公用信息对应的Bean,每个开发人员根据自己的模块需求,制作独立的配置文件

  applicationContext-user.xml

  applicationContext-book.xml

  applicationContext-order.xml

6.多配置文件加载ApplicationContext对象

  格式一:

    在子配置文件中导入主配置文件

    <import resource="applicationContext.xml"/>

    加载ApplicatioContext对象是需要加载子配置文件即可

    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-user.xml");

  格式二:

    一次性加载多个配置文件(可变参数对象格式)

    ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml","bean2.xml");

  格式三:

    一次性加载多个配置文件(数组对象格式)

    ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"bean1.xml","bean2.xml"});

Bean配置(注解)【了解】【操作】

Spring2.5提供使用注解的形式配置Bean

1.配置Bean使用@Component注解

  如需为Bean定义名称,在参数中添加Bean名称@Component("beanName")

2.设定Spring的自动扫描路径,用于检测对应的Bean是否配置了注解,并加载配置了注解的类

  a)开启context空间的支持

复制代码
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
复制代码

  b)开启自动扫描功能,并指定扫描的路径

  <context:component-scan base-package="cn.itcast.annotation"></context:component-scan>

  说明:扫描路径可以设置多个,中间使用,隔开,扫描路径包含指定包和子包内所有的类

3.Spring提供了3个注解开发Bean的兼容格式,用于后期分层设计扩展

  @Repository 用于数据层实现类标注

  @Service 用于业务逻辑层实现类标注

  @Controller 用于控制层实现类进行标注

4.Bean注入简单类型属性

  a)在属性名上方声明该属性自动装配@Autowired

  b)在属性名上方声明该属性注入的值@Value(value)

  @Autowired

  @Value("itcast")

  private String msg;

  注意:注解自动装配属性值无需提供对应属性的setter方法

5.Bean注入引用类型属性

  a)在属性名上方声明该属性自动装配@Autowired

  b)在属性名上方声明该属性注入的值@Qualifier(bean引用名称)

  @Autowired

  @Qualifier("anno2")

  private AnnotationOther other;

  注意:被注入的Bean一定要存在,无需提供对应属性的setter方法

6.@Autowired注解属性required用于声明自动装配的数据是否是必须的

  如果required=true,必须为其装配数据,如果没有值,抛出异常

  如果required=false,自动装配数据失败,则注入值为null

7.Spring支持JSR-250规范提供的@Resource注解的支持

  格式一:@Resource(name="myImpl")

  格式二:@Autowired(required=false)

        @Qualifier("myImpl")

  以上两种格式效果相同

8.Bean声明周期注解

  @PostConstruct

  功能:为当前Bean指定init-method参数

  格式:定义在成员方法的上方,兼容静态方法

  @PreDestroy

  功能:为当前Bean指定destory-method参数

  格式:定义在成员方法的上方,兼容静态方法

  注意:要求当前类被注册为Bean,否则无效果

9.Bean作用域注解

  在类的定义上方添加@Scope指定Bean的作用域

  常用:@Scope("prototype")

  默认:@Scope("singleton")

10.Spring3.0注解支持

  @Configuration配置当前类为配置类,用于加载其中配置的Bean,与静态工厂初始化Bean很相似

  @Bean(name="b1")将配置类中的某个方法的返回值声明为Bean,该方法必须返回一个对象

  @Configuration //设定该类参与自动扫描

复制代码
public class MyBeanFactory {
  @Bean(name={"aa","bb","cc"}) //设定该方法的返回值是一个Bean
  public static BookService getInst(){
    return new BookService();
  }
}
复制代码

 

 

 

以上操作必须基于自动扫描功能,如不开启自动扫描,Spring将无法查找到对应的注解配置

11.可以不使用自动扫描使用Bean

  AnnotationConfigApplicationContext对象可以手工加载基于注解配置的Bean

  //用于手工添加注解开发Bean的上下文对象

  AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();

  //加载配置管理类

  ctx.register(MyConfiguration.class);

  //刷新上下文对象

  ctx.refresh();

  注意:注册完成后一定要进行刷新,否则加载的Bean将无法被使用

Spring整合JUnit【了解】【操作】

Spring提供了对JUnit的整合支持

操作步骤

1.导入测试Jar

spring-test-3.2.0.RELEASE.jar

2.设置类运行器(注解添加到运行程序类的上方)

  @RunWith(SpringJUnit4ClassRunner.class)

3.设置读取Spring的配置文件路径

  @ContextConfiguration(locations="classpath:/applicationContext.xml")

范例:

  @RunWith(SpringJUnit4ClassRunner.class) //设置JUnit运行器为Spring

  @ContextConfiguration(locations={"classpath:/applicationContext-junit.xml"}) //加载配置

复制代码
public class App {
  //要测试的Bean必须称为测试类的属性注入进来,然后对其进行测试
  @Autowired
  @Qualifier("testBean")
  private Bean1 testBean;
  @Test
  public void testJunit(){
    testBean.fn();
  }
}
复制代码

 

注意:使用junit整合spring时,必须保障运行类中要入要测试的Bean。整合完毕后,当前的测试类

将作为SpringBean出现,而测试的Bean对象作为测试类的注入资源进行运行。

AOP简介【理解】【重点】

1.AOP(Aspect Oriented Programing)面向切面/方面编程

2.AOP隶属软件工程的范畴,指导开发人员如何制作开发软件,进行结构设计

3.AOP联盟:掌握着AOP的发展方向

4.AOP开发只关注共性功能

5.主思想:在不惊动原始设计的基础之上,为原始设计追加功能

  *插拔式组件体系结构

  *OOPAOP区别

    OOP开发,关注的是层与层之间的关系,及其每层中各个实现类如何制作

    AOP开发,关注的是共性功能,无论该共性功能是否服务于同一层面的类

    将共性功能抽取出来,制作成独立的模块,在程序运行时,动态的为其追加该功能

6.AOP核心思想

  AOP关注的是程序中的共性功能,开发时,将共性功能抽取出来制作成独立的功能模块,此时原始功能中将不具有这些被抽取出的共性功能代码。在当时具有被抽取的共性功能的模块运行时候,将共性功能,模块进行运行,即可完成原始的功能。

  优点:加强代码的复用性,同时程序开发时可以只考虑个性化的功能,不需要考虑共性功能

AOP基本概念【理解】【重点】

连接点(Joinpoint):类中的任意方法的运行时表示,可以简单理解为类中的方法

切入点(Pointcut) :具有共性功能的方法的运行时表示,可以简单理解为具有共性功能的方法

注意:切入点对应的是被挖去了共性功能后的方法执行时匹配断言(格式)

通知(Advice) :共性功能模块化,可以简单理解为将共性功能抽取出来制作成独立的方法

切面(Aspect) :切入点与通知的对应关系,可以简单理解为被抽取的共性功能与共性功能被抽取位置对应的方法之间的关系

目标对象(Target Object) :包含切入点的运行时对象,开发阶段制作的是目标对象对应的类

l AOP代理(AOP Proxy) :使用AOP的代理机制创建目标对象运行时代理对象,完成原始的功能

注意:原始目标对象已经被挖去了共性功能,此时使用目标对象执行任务无法完成原始任务,使用AOP代理机制,创建一个代理对象来完成原始目标对象的功能

织入(Weaving) :是一个将通知功能加入原始字节码的动态过程,共有三种方式,Spring使用的是运行时织入机制

l 【了解】引入(Introduction) :一种特殊的机制,可以为一个类的字节码动态的加入变量或方法

AOP工作流程:

开发时,制作功能类(目标对象类),将其中方法的通用功能(通知)抽取出来,制作成独立的类(通知类),原始目标对象中的方法(切入点)不再书写通用功能。通用功能被抽取后,原始目标对象无法完成完整的业务逻辑,需要在运行时将通知加入到对应的位置执行。为了完成此操作,必须将切入点与通知进行一对一的对应关系设定(切面)。

AOP运行流程:

运行时,Spring监控切面中所配置切入点对应方法的执行,发现执行了匹配的方法,使用AOP代理机制,创建代理对象(AOP代理),将原始方法(切入点)与通知进行融合,形成完整的业务逻辑并进行运行,此过程称为织入。

AOPXML【理解】【应用】【重点】

1.AOP基础实例

  A.导入jar

    核心包(4) 日志(2) AOP(4)

    Spring进行AOP开发(1)(3.2资源包)

    spring-aop-3.2.0.RELEASE.jar

    Spring整合AspectJ框架(3.2资源包)

    spring-aspects-3.2.0.RELEASE.jar

    AOP联盟规范(1) (3.0.2依赖包)

    com.springsource.org.aopalliance-1.0.0.jar

    aspectJ支持(1) (3.0.2依赖包)

    com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

  B.制作目标对象类(配置成Bean

复制代码
public class UserImpl {
  //当前类的三个方法中具有共性功能System.out.println("共性功能1");  抽取出来
  public void add(){
    //共性功能1被抽取走了,放入到了MyAdvice类中的functionOne方法里
    System.out.println("共性功能2");
    System.out.println("user add....");
  }
}
复制代码

 

 

 

    注意:共性功能被抽取后,不是在原始位置进行调用,而是将共性功能删除

  C.将抽取的功能制作成通知(配置成Bean

public class MyAdvice {
  //被抽取的共性功能1
  public void functionOne(){
    System.out.println("共性功能1");
  }
}

 

 

 

    说明:被抽取的共性功能制作成独立的类中方法。由于要将两个对象中的内容融合,Spring在控制其融合的过程必须控制两个对象,因此需要分别将两个类配置为Spring管理的Bean

  D.开启AOP空间的支持

复制代码
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
复制代码

  E.配置AOP的切面

复制代码
<!-- 配置AOP -->
<aop:config>
  <!-- 配置切面,指定切面类的Bean:配置切入点与通知之间的关系 -->
  <!-- ref:配置切面对应的Bean -->
  <aop:aspect ref="myAdvice">
  <!-- 声明通知的类别是何种类型  前置通知-->
  <!-- 配置前置通知 -->
  <!-- aop:before表示在原始方法执行前追加功能 -->
  <!-- pointcut:配置Spring监控的方法切入点 -->
  <!-- method:配置的切面类中对应的共性功能-方法名称 -->
    <aop:before pointcut="execution(* cn.itcast.aop.one.UserImpl.add())" method="functionOne"/>
  </aop:aspect>
</aop:config>
复制代码

 

 

 

  F.制作Spring格式的客户端程序测试

  ApplicationContext ctx = new ClassPathXmlApplicationContext(“applicationContext.xml”);
  UserDao dao = (UserDao)ctx.getBean(“userDao”);
  dao.add();

2.切入点表达式

  格式:execution(切入点表达式)

  execution([方法的访问控制修饰符方法的返回值 包名.类名/接口名.方法名(参数))

  注意:方法的访问控制修饰符可以省略

  范例:

  public void cn.itcast.UserDAO.add() 公共的cn.itcat包中的UserDAO类的无参数无返回值的add方法

  void cn.itcast.UserDAO.add() 公共的cn.itcat包中的UserDAO类的无参数无返回值的add方法

  方法的返回值可以写具体的返回值,或者写*表示任意返回值

  void cn.itcast.UserDAO.add() 公共的cn.itcat包中的UserDAO类的无参数无返回值add方法

  * cn.itcast.UserDAO.add() 公共的cn.itcat包中的UserDAO类的无参数不限定返回值add方法

  包名,方法名

  * cn.itcast.*.dao.UserDAO.add() cn包下的itcast包下的任意包下的dao包下的…..

  * cn.itcast..dao.UserDAO.add() cn包下的itcast包下的任意层包下的dao包下的…..

  * *..*.*() 任意包下的任意类中的任意方法

  参数

  add() 无参数

  add(*) 一个参数

  add(int) 一个int型参数

  add(*,*) 两个参数

  add(*,int) 两个参数,第一个任意,第二个int

  add(..) 任意参数

  add(*,..) 至少一个参数

特殊格式:

  * cn.itcast.UserDAO.add(..) && args(int,int) 错误

  * cn.itcast.UserDAO.add(..)  &&  args(int,int) 正确

  * cn.itcast.UserDAO.add(int,int)  &&  args(a,b) 不常用,正确

  * cn.itcast.UserDAO.add(int,int)  &&  args(b,a) 不常用,正确

3.切入点配置方式

   切入点配置时,可以设置切面间共享切入点,也可以设置切面内共享切入点,还可以设置局部切入点

格式一:配置在通知类别后面

<aop:before   pointcut="execution(public void *..*.*Impl.a*())"  ….

格式二:配置在某个切面中,在当前切面范围内共享

<aop:aspect ref="myAdvice">

<!-- 配置同一个切面中使用的公共切入点 -->

<aop:pointcut expression="execution(public void *..*.*Impl.a*())" id="pt2"/>

<aop:before   pointcut-ref="pt2" …..

格式三:配置在AOP总配置中,在全部范围内共享

<aop:config>

<aop:pointcut expression="execution(public void *..*.*Impl.a*())" id="pt1"/>

<aop:aspect ref="myAdvice">

<aop:before pointcut-ref="pt1"……

</aop:aspect>

</aop:config>

范例:

<aop:config>

<!-- 所有切面共享的切入点 -->

<aop:pointcut expression="execution(* cn.itcast..*Tar*.*())" id="pt"/>

<aop:aspect ref="myAdvice">

<!-- 在一个切面内共享的切入点:配置独立的切入点表达式对象 -->

<aop:pointcut expression="execution(* cn.itcast..*Tar*.*(..))" id="pt1"/>

<aop:before pointcut-ref="pt" method="fn"/>

<aop:before pointcut="execution(* *..*.*(..))" method="fn"/>

</aop:aspect>

<aop:aspect ref="myAdvice">

<!-- 配置独立的切入点表达式对象 -->

<aop:pointcut expression="execution(* cn.itcast..*Tar*.*(..))" id="pt2"/>

<aop:before pointcut-ref="pt" method="fn"/>

<aop:before pointcut-ref="pt" method="fn"/>

</aop:aspect>

</aop:config>

4.通知类别

  通知共有五种类别

    before:在原始操作前运行

    after: 在原始操作后运行,无论方法是否抛出异常

    afterReturning:在原始操作后运行,只有方法正常结束才运行,抛出异常则不运行

    afterThrowing:在原始操作中如果抛出异常,运行

    around: 在原始操作前后运行,通过ProceedingJoinPoint对象调用procee()方法完成对原始操作的调用

复制代码
    //环绕通知
    public void around(ProceedingJoinPoint pjp) throws Throwable{
      System.out.println("around before......");
      //调用原始方法
      pjp.proceed();
      System.out.println("around after......");
    }
复制代码

  通知的配置格式

    <aop:before pointcut-ref="pt2" method="before"/>

    <aop:after pointcut-ref="pt2" method="after"/>

    <aop:after-returning pointcut-ref="pt2" method="afterReturning"/>

    <aop:after-throwing pointcut-ref="pt2" method="afterThrowing"/>

    <aop:around pointcut-ref="pt2" method="around"/>

5.通知顺序

  在切入点之前运行的通知

  执行允许与配置顺序有关,在上面的先运行

  在切入点之后运行的通知

  在同一个切面中执行允许与配置顺序有关,在上面的先运行

  在不同的切面中执行允许与配置顺序有关,与切面的配置顺序相反

  总结:不同通知类型执行的顺序以配置顺序为准

6.获取通知参数

  为环绕通知之外的通知方法定义形参JoinPoint,该参数必须是通知方法的第一个参数

  获取参数:Obejct[] args = jp.getArgs();

  范例:

public void before(JoinPoint jp){

Object[] objs = jp.getArgs();

System.out.println("before......"+objs[0]+","+objs[1]);

}

为环绕通知方法定义形参ProceedingJoinPoint对象

获取参数:Obejct[] args = pjp.getArgs();

7.获取通知返回值

afterReturning 与 around可以获取方法的返回值

A.around通知获取返回值

ProceedingJoinPoint对象执行调用原始操作的返回值就是原始方法的运行返回值

Object res = pt.proceed(args);

注意:如果原始方法返回值为void类型,则around方法返回值设置为Object

如果原始方法返回值为非void类型,则around方法内必须将原始方法调用的结果返回

原始方法返回值为void类型的,通知内获取的返回值统一为null

public Object around(ProceedingJoinPoint pjp) throws Throwable{

Object res = pjp.proceed(args);

return res;

}

B.afterReturning通知获取返回值

在通知方法的参数中,声明一个Object类型的参数,用于保存方法的返回值

public void afterReturning(JoinPoint jp,Object abc){

System.out.println("afterReturning......"+ abc);

}

在配置文件中,为afterReturning声明保存返回值的变量名

<aop:after-returning  method="afterReturning" returning="abc"/>

8.获取通知异常对象

异常对象的获取方式与返回值很相似,声明变量,在配置中声明保存异常对象的变量名

<aop:after-throwing pointcut-ref="pt" method="afterThrowing" throwing="e"/>
public void afterThrowing (Throwable e){
  System.out.println("afterThrowing......."+ e);
}

 

AOP(注解)【理解】【应用】【重点】

1.AOP注解配置流程

  A.开启AOP配置支持注解@aspectj

    核心配置文件中添加以下配置,功能等同于注解配置Bean的自动扫描路径

    <aop:aspectj-autoproxy/>

  B.将所有参与AOP配置的类声明为Spring控制的Bean

    可以使用XML配置格式或注解格式

  C.在切面类的类定义上方添加切面的声明

    @Aspect

    public class MyAdvice {…}

  D.将切面类中的方法配置为指定类型的通知,配置时指定其切入点

@Before("execution(* cn.itcast.aop.annotation.UserImpl.add())")
public void before(JoinPoint jp) {
  System.out.println("before");
}

 

 

 

2.配置公共的切入点

A.在切面类中声明一个方法(私有的),将该方法配置为切入点

  @Pointcut("execution(* cn.itcast.aop.annotation.UserImpl.add())")

  private void pt(){}

B.使用配置的切入点

  @Before("引用切入点")

  格式:切面类名.方法名()

  范例:@Before("MyAdvice. pt ()")

3.注解开发通知的通知类别

  前置通知 @Before(value="execution(* *..*.*(..))")

  后置通知 @After(value="execution(* *..*.*(..))")

  抛出异常通知 @AfterThrowing(value="execution(* *..*.*(..))",throwing="ex")

  返回后通知 @AfterReturning(value="execution(* *..*.*(..))",returning="ret")

  环绕通知 @Around(value="execution(* *..*.*(..))")

4.注解格式AOP顺序

  总体顺序由上到下为下列描述顺序

  around before

  before

  around after

  after

  afterReturning

实际开发以最终运行顺序为准

5.返回值与异常对象的获取方式

@AfterReturning(value="MyAdvice.pt()",returning="aa")
public void afterReturning(JoinPoint jp,Object aa){
  System.out.println("afterReturning......."+aa);
}

 

 

 

 

CGLIB【理解】【难点

1.AOP内部工作原理是通过代理对象实现织入功能

对于有接口实现的对象使用JDK动态代理

对于无接口实现的对象使用Cglib动态代理

2.CGLIBcode generator library)代码生成库——第三方技术

作用:动态的生成字节码

CGLIB中的核心对象是Enhance对象,它的作用是创建一段动态的类字节码。

CGLIB可以对任意的类进行代理,JDK的代理只能对实现接口的类进行代理

public class MyCglibProxyObject implements MethodInterceptor {

//提供一个方法用于创建Animal类的代理对象

public Animal createCglibProxyObject(){

//1.在内存中创建一个动态的类的字节码

Enhancer enhancer = new Enhancer(); //此时并没有做继承

//2.为其指定父类

//除了完成继承关系外,还将父类所有的方法名反射过来,并在自己的类中创建了这些方法

enhancer.setSuperclass(Animal.class);

//3.指定其回调操作

enhancer.setCallback(this);

//4.使用该类创建对象

return (Animal) enhancer.create();

}

public Object intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {

if(method.getName().equals("eat")){

System.out.println("吃前来个开胃菜");

}

return methodProxy.invokeSupper(proxy, args);

}

}

DAO模板类【了解】

1.Spring提供有DAO支持模板类,功能类似于Apache DBUtils

  JdbcTemplate

  HibernateTemplate

  SqlMapClientTemplate(过时)

  JpaTemplate (过时)

2.基础实例

  A.导入jar

    核心包(4)

    日志(2)

    jdbc模板支持(1)

    spring-jdbc-3.2.0.RELEASE.jar

    模板相关事务处理包(1)

    spring-tx-3.2.0.RELEASE.jar

    数据库连接驱动包

    mysql-jdbc.jar

  B.JDBC模板类使用(编程式)

    //创建Spring对应的数据源对象

    //数据源描述的是一系列的相关描述信息的封装对象

    DriverManagerDataSource dataSource = new DriverManagerDataSource();

    //为数据源对象提供数据库连接的相关数据(4)

    dataSource.setDriverClassName("com.mysql.jdbc.Driver");

    dataSource.setUrl("jdbc:mysql://localhost:3306/springdb");

    dataSource.setUsername("root");

    dataSource.setPassword("root");

    //创建JDBC模板类,需要使用数据源对象

    JdbcTemplate template = new JdbcTemplate(dataSource);

    //执行添加语句

    template.execute("insert into tbl_user values(null,'jock',34)");

    template.execute("update tbl_user set userName='jockme' where uuid=1");

3.使用Spring形式开发JDBCTemplate

A.DAO中声明JDBCTemplate变量

B.提供setter注入

C.DAO声明为Bean,为其注入JDBCTemplate

<!-- UserDao -->

<bean id="userDao" class="cn.itcast.jdbc.UserDAO">

<property name="jdbcTemplate" ref="jdbcTemplate"/>

</bean>

D.声明JDBCTemplateBean,为其注入DataSource

<!-- JDBCTemplate -->

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">

<property name="dataSource" ref="dataSource"/>

</bean>

E.声明DataSourceBean,为其注入DataSource需要使用的数据库连接参数

<!-- Spring内置的DataSource -->

<bean id=" dataSource " class="org.springframework.jdbc.datasource.DriverManagerDataSource">

<property name="driverClassName" value="com.mysql.jdbc.Driver"/>

<property name="url" value="jdbc:mysql://localhost:3306/springdb"/>

<property name="username" value="root"/>

<property name="password" value="root"/>

</bean>

4.数据源配置格式(3种)

Spring内置的DataSource

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>

<property name="url" value="jdbc:mysql://localhost:3306/springdb"></property>

<property name="username" value="root"></property>

<property name="password" value="root"></property>

</bean>

使用DBCP,需要导入对应的jar

com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar

com.springsource.org.apache.commons.pool-1.5.3.jar

<!-- 声明DBCPDataSource -->

<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource">

<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>

<property name="url" value="jdbc:mysql://localhost:3306/springdb"></property>

<property name="username" value="root"></property>

<property name="password" value="root"></property>

</bean>

使用c3p0,需要导入对应的jar

com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar

<!-- 声明c3p0的数据源DataSource -->

<bean id="dataSource3" class="com.mchange.v2.c3p0.ComboPooledDataSource">

<property name="driverClass" value="com.mysql.jdbc.Driver"></property>

<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/springdb"></property>

<property name="user" value="root"></property>

<property name="password" value="root"></property>

</bean>

5.用外部properties格式文件,输入参数

A.制作独立的属性文件jdbc.properties放置到src目录下,用于保存数据库连接的相关参数

driverClass=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/springdb

jdbc_username=root

password=root

B.加载属性文件到Spring配置中

方式一:不推荐使用

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

<property name="location" value="classpath:jdbc.properties"></property>

</bean>

方式二:推荐使用

<context:property-placeholder location="classpath:jdbc.properties"/>

注意:方式二可以使用通配符格式classpath:*.properties格式,一次加载所有的配置文件,但是,该方式要加载所有的系统配置,因此属性文件中的属性名不要与系统属性冲突。userName特别注意

C.将固定的参数改为引用属性文件中的参数

格式:${属性名}  ${userName} ${url}    ${password}  ${jdbc_user}

DAO支持抽象类【理解】【操作】

1.使用统一的DAO支持抽象类,可以简化开发过程,数据层实现类继承JdbcDaoSupport

public class UserDAO extends JdbcDaoSupport{…}

2.为该类注入DataSource

<bean id="userDao" class="cn.itcast.jdbc.template.UserDAO">

<!-- 必须为继承JdbcDaoSupport的类注入JdbcTemplate,变量名为jdbcTemplate -->

<!-- <property name="jdbcTemplate" ref="jdbcTemplate"/> -->

<!-- 还可以注入DataSource对象,由JdbcDaoSupport自动创建JdbcTemplate对象 -->

<property name="dataSource" ref="dataSource"/>

</bean>

3.DAO实现类中使用this.getJdbcTemplate()获取模板对象

4.JdbcTemplate API

增删改

update(sql,Object... args)

查询数据为单一结果数据

queryFor* 获取简单类型数据

Long queryForLong(sql,Object... args)

Interget queryForInt(sql,Object... args)

Double queryForDouble(sql,Object... args)

queryForObject 获取引用类型数据(不是全部)

Object<T> queryForLong(sql,查询数据的类型class,Object... args)

查询数据为全部字段的单一数据

queryForObject

Object queryForObject(sql,查询数据结果行映射接口对象,Object... args)

查询数据为全部字段的多条数据

query

List<T> query (sql,查询数据结果行映射接口对象,Object... args)

行映射接口制作

private class 自定义内部类类名 implements RowMapper<实体泛型>{

public User mapRow(ResultSet rs, int rownum) throws SQLException {

User u = new User(); //实体

通过原始的jdbc查询结果集对象ResultSet获取查询的数据

u.setUuid(rs.getLong("uuid"));

u.setUserName(rs.getString("userName"));

u.setAge(rs.getInt("age"));

return u;

}

}

标准DAO制作范例:

public void add(UserModel um){

String sql = "insert into tbl_user (userName,age) values(?,?)";

this.getJdbcTemplate().update(sql, um.getUserName(),um.getAge());

}

public void delete(UserModel um){

String sql = "delete from tbl_user where uuid = ?";

this.getJdbcTemplate().update(sql, um.getUuid());

}

public void update(UserModel um){

String sql = "update tbl_user set userName = ? , age = ? where uuid = ?";

this.getJdbcTemplate().update(sql, um.getUserName(),um.getAge(),um.getUuid());

}

//查询一共多少条数据

public Integer getCount(){

String sql = "select count(uuid) from tbl_user";

return this.getJdbcTemplate().queryForInt(sql);

}

//按照uuid查名字

public String getNameByUuid(Long uuid){

String sql = "select userName from tbl_user where uuid = ?";

return this.getJdbcTemplate().queryForObject(sql,String.class,uuid);

}

//查询某个数据

public UserModel getByUuid(Long uuid){

String sql = "select * from tbl_user where uuid = ?";

RowMapper<UserModel> rm = new RowMapper<UserModel>() {

public UserModel mapRow(ResultSet rs, int rowNum)throws SQLException {

UserModel um = new UserModel();

um.setUuid(rs.getLong("uuid"));

um.setUserName(rs.getString("userName"));

return um;

}

};

return this.getJdbcTemplate().queryForObject(sql, rm, uuid);

}

//查询全部数据

public List<UserModel> getAll(){

String sql = "select * from tbl_user";

RowMapper<UserModel> rm = new RowMapper<UserModel>() {

public UserModel mapRow(ResultSet rs, int rowNum)throws SQLException {

UserModel um = new UserModel();

um.setUuid(rs.getLong("uuid"));

um.setUserName(rs.getString("userName"));

return um;

}

};

return this.getJdbcTemplate().query(sql, rm);

}

事务管理基本概念【了解】

1.事务管理相关接口PlatformTransactionManager

DataSourceTransactionManager

使用Spring JDBC或iBatis 进行持久化数据时使用

HibernateTransactionManager

使用Hibernate3.0版本进行持久化数据时使用

获取事务状态信息

TransactionStatus getTransaction(TransactionDefinition definition)

提交事务

void commit(TransactionStatus status)

回滚事务

void rollback(TransactionStatus status)

2.TransactionDefinition

获取事务名称

String getName()

获取事务隔离级

int getIsolationLevel()

获取事务传播行为

int getPropagationBehavior()

获取事务超时时间

int getTimeout()

获取事务是否只读

boolean isReadOnly()

3.TransactionStatus

刷新事务

void flush()

获取是否存在存储点

boolean hasSavepoint()

获取事务是否完成

boolean isCompleted()

获取事务是否为新的事务

boolean isNewTransaction()

获取事务是否回滚

boolean isRollbackOnly()      

设置事务回滚

void setRollbackOnly()

4.事务隔离级反映事务提交并发访问时的处理态度

ISOLATION_DEFAULT 默认级别,归属下列某一种

ISOLATION_READ_UNCOMMITTED 可以读取未提交数据

ISOLATION_READ_COMMITTED 只能读取已提交数据,解决脏读问题(Oracle默认级别)

ISOLATION_REPEATABLE_READ

是否读取其他事务提交修改后的数据,解决不可重复读问题(MySQL默认级别)

ISOLATION_SERIALIZABLE

是否读取其他事务提交添加后的数据,解决幻影读问题

编程式事务【了解】【难点

1.案例环境:银行转账业务A账户到B账户操作

表结构

CREATE TABLE `tbl_account` (

  `uuid` bigint(10) NOT NULL,

  `name` varchar(30) NOT NULL,

  `money` double(10,2) NOT NULL,

  PRIMARY KEY  (`uuid`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `tbl_account` VALUES ('1', 'tom', '1000.00');

INSERT INTO `tbl_account` VALUES ('2', 'jerry', '1000.00');

数据层制作接口与实现类

public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{

public void inMoney(String in, Double money) {

String sql = "update tbl_account set money = money + ? where name = ?";

this.getJdbcTemplate().update(sql,money,in);

}

public void outMoney(String out, Double money) {

String sql = "update tbl_account set money = money - ? where name = ?";

this.getJdbcTemplate().update(sql,money,out);

}

}

业务层制作接口与实现类

public class AccountServiceImpl implements AccountService {

private AccountDao accountDao;

public void setAccountDao(AccountDao accountDao) {

this.accountDao = accountDao;

}

public void transfer(String out, String in, Double money) {

//一个人减钱

accountDao.outMoney(out, money);

//一个人加钱

accountDao.inMoney(in, money);

}

}

配置对应的Bean

<!-- Service -->

<bean id="accountService" class="cn.itast.tx.account.AccountServiceImpl">

<property name="accountDao" ref="accountDao"/>

</bean>

<!-- DAO -->

<bean id="accountDao" class="cn.itast.tx.account.AccountDaoImpl">

<property name="dataSource" ref="dataSource"/>

</bean>

<!-- DataSource -->

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

<property name="driverClassName" value="com.mysql.jdbc.Driver"/>

<property name="url" value="jdbc:mysql://localhost:3306/springdb"/>

<property name="username" value="root"/>

<property name="password" value="root"/>

</bean>

2. TransactionTemplate

TransactionTemplate事务模板对象,用于完成事务操作,使用execute方法完成

业务层通过TransactionTemplate对象完成将多个操作制作成同一事务

private TransactionTemplate transactionTemplate;

public void setTransactionTemplate(TransactionTemplate transactionTemplate) {

this.transactionTemplate = transactionTemplate;

}

public void transfer(final String out,final  String in,final  Double money) {

TransactionCallback tc = new TransactionCallbackWithoutResult() {

protected void doInTransactionWithoutResult(TransactionStatus arg0) {

//在当前方法中运行的所有操作处于同一个事务

accountDao.outMoney(out, money);

accountDao.inMoney(in, money);

}

};

//事务管理操作

transactionTemplate.execute(tc);

}

3.业务层Bean注入事务管理模板

<bean id="accountService" class="cn.itast.tx.account.AccountServiceImpl">

<property name="accountDao" ref="accountDao"/>

<property name="transactionTemplate" ref="transactionTemplate"/>

</bean>

4.声明一个事务管理模板Bean,该Bean依赖与事务管理器对象

<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">

<property name="transactionManager" ref="transactionManager"/>

</bean>

5.声明一个事务管理器的Bean,该Bean依赖与DataSource运行,该DataSource必须与数据层操作注入的DataSource相同

<bean id="transactionManager"

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dataSource"/>

</bean>

声明式事务(XML【理解】【重点】

思路分析:将编程式事务中的通用代码抽取出来,制作成独立的around通知使用AOP工作原理,将事务管理的代码动态织入到原始方法中。由于该功能使用量较大,Spring已经将该通知制作完毕。

1.开启tx命名空间

复制代码
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
">
复制代码

2.定义Spring提供的事务管理通知

<!-- 事务管理Advice,Spring提供 -->

<tx:advice id="txAdvice" transaction-manager="txManager">

<tx:attributes>

<tx:method name="transfer"/>

</tx:attributes>

</tx:advice>

注意:TxAdvice需要为其指定一个事务管理器的Bean

<!-- 声明事务管理器的Bean,该Bean依赖数据源对象 -->

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dataSource"></property>

</bean>

3.设置AOP

<aop:config>

<aop:advisor advice-ref="txAdvice" pointcut="execution(void *..*.*.trans*(..))"/>

</aop:config>

4.将原始编程式事务控制中的控制代码删除

5.advice的参数

tx:advice:定义事务管理的通知(环绕通知)

transaction-manager:声明事务管理的实现类

tx:method:定义参与事务管理的方法

6.method的参数

参数名

实例

作用

name

name=“get*”

定义参与事务管理的方法,支持通配符

timeout

timeout=-1

定义事务超时时间,-1为永不超时

read-only

read-only=“false”

定义事务种类为只读事务或读写事务

no-rollback-for

异常名称

定义不参与事务回滚的异常名

rollback-for

异常名称

定义参与事务回滚的异常名

isolation

Isolation

定义事务隔离级

propagation

propagation

定义事务的传播属性

7.事务传播行为

配置的是事务协调员(事务加入者)针对事务管理员(事务发起者)所携带的事务的处理态度

事务管理者(业务) 事务协调员(数据)

REQUIRED T1 T1

无 T2

REQUIRES_NEW T1 T2

无 T1

SUPPORTS T1 T1

无 无

NOT_SUPPORTED T1 无

无 无

MANDATORY T1 T1

无 错误

NEVER T1 错误

无 OK

NESTED savePoint()


声明式事务(注解)【理解】【应用】【重点】

1.对要添加事务的类或接口定义上方声明@Transactional

也可以将注解添加到方法上,指定某个方法添加事务

2.在配置文件中,开启注解式事务驱动,需要为其指定事务管理器

<tx:annotation-driven transaction-manager="txManager"/>

3.定义事务管理器,根据使用的具体实现方式设置

<bean id=" txManager " class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dataSource"></property>

</bean>

4.为事务管理器注入dataSource

5.事务属性通过注解参数完成

@Transactional(

isolation=Isolation.READ_COMMITTED,

propagation=Propagation.NEVER,

readOnly=true,

noRollbackForClassName={"java.lang.ArithmeticException","",""}, 异常名称字符串数组

noRollbackFor={java.lang.ArithmeticException.class,java.lang.NullPointerException.class},

timeout=30

)

6.实际开发技巧:

业务层接口上方声明注解式事务@Transactional

 

SSH整合(XML【理解】【应用】【重点】

1.jar包整合

Struts2:

必备包+strutsspring整合的插件包

基本jar(11)

struts-2.3.7-all.zip资源包中获取apps目录下对应jar

apps\struts2-blank\WEB-INF\lib\*.jar

相关jar(1+2)

struts2整合Spring(需要使用)

struts2-spring-plugin-2.3.7.jar

struts2整合Ajax(通常需要使用)

struts2-json-plugin-2.3.7.jar

struts2使用注解开发(根据需求开启)

struts2-convention-plugin-2.3.7.jar

配置文件:

struts.xml

web.xml

web.xml文件中要添加struts2的核心过滤器,否则无法使 struts拦截请求

Spring3:

核心jar(4)

spring-beans-3.2.0.RELEASE.jar

spring-context-3.2.0.RELEASE.jar

spring-core-3.2.0.RELEASE.jar

spring-expression-3.2.0.RELEASE.jar

日志包(2)

com.springsource.org.apache.commons.logging-1.1.1.jar

com.springsource.org.apache.log4j-1.2.15.jar

AOP(4)

spring-aop-3.2.0.RELEASE.jar

spring-aspects-3.2.0.RELEASE.jar

com.springsource.org.aopalliance-1.0.0.jar

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

JDBC(2)

spring-jdbc-3.2.0.RELEASE.jar

spring-tx-3.2.0.RELEASE.jar

整合ORM框架(1)

spring-orm-3.2.0.RELEASE.jar

WEB集成(1)

spring-web-3.2.0.RELEASE.jar

配置文件:

applicationContext.xml

web.xml文件中添加springIoC容器加载监听器

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:applicationContext.xml</param-value>

</context-param>

log4j.properties

log4j.rootLogger=info,console

log4j.appender.console=org.apache.log4j.ConsoleAppender

log4j.appender.console.layout=org.apache.log4j.PatternLayout

log4j.appender.console.layout.ConversionPattern=%d %5p %c{1}:%L - %m%n

Hibernate

核心jar(1)

hibernate3.jar

必须的jar(6)

lib\required\目录下的所有包

antlr-2.7.6.jar

commons-collections-3.1.jar

dom4j-1.6.1.jar

javassist-3.12.0.GA.jar

jta-1.1.jar

slf4j-api-1.6.1.jar

jpajar(1)

hibernate-jpa-2.0-api-1.0.1.Final.jar

slf4j整合log4jjar(1) (log4jspring中已导入)

slf4j-log4j12-1.7.2.jar

配置:

hibernate.cfg.xml

Model.hbm.xml

其他Jar

数据库连接包

log4j包(已经导入)

2.spring如何整合Web

使用监听器完成spring环境进入web容器,当web容器启动时,监听器将启动,加载配置中的配置

文件,并将spring上下文对象加载到ServletContext范围下

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:applicationContext*.xml</param-value>

</context-param>

3.sturts2spring整合

  A.调试struts2,保障其正常工作

  B:将strutsspring整合

    struts中使用springBean的方式共有4

  I.直接创建ApplicationContext对象

    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

    UserEbi userEbi = (UserEbi) ctx.getBean("userEbi");

  优点:容易掌握

  缺点:每个操作都要重新加载配置文件,工作量巨大,并且加载的配置只能使用一次

解决方案一:将该对象设置为类级别属性或更高级别的属性

II.ApplicationContext对象放置到更大的范围中,例如web环境中

依赖web.xml文件中的监听器完成该工作

ServletContext sc = ServletActionContext.getServletContext();

WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sc);

优点:解决了ApplicationContext对象的多次加载问题

缺点:操作过于繁琐

解决方案二:能不能不写该操作

III.使用struts2spring整合的插件包

基于插件包中的配置<constant name="struts.objectFactory" value="spring" />

此时Struts对象的属性可以使用spring的自动装配模式,默认按照name装配

struts.objectFactory.spring.autoWire = name

此时struts的对象工厂由Spring进行控制,需要的属性spring自动装配/注入

优点:操作模式及其简洁

缺点:目前StrutsAction类的对象是由struts控制创建的

解决方案三:将struts的对象交由spring 管理

IV.Action配置为Bean

Action类配置成SpringBean

struts.xml中修改Action类的class属性为Bean的名称,该名称称为伪类名

此时Spring管理Action

优点:所有对象集中在springIoC容器中进行管理

缺点:没有缺点

注意:ActionBean配置时,千万要记得配置scope=prototype

4.hibernate3spring整合

整合Hibernate有两种格式

引入式整合(少用)

独立整合(主流)

引入式整合:

A.DAO类的制作要求继承HibernateDaoSupport

该类需要注入SessionFactory,注入setter方法已经由父类定义,无需手工书写

B.DAO类中注入SessionFactory,首先声明Bean

<!-- Dao -->

<bean id="userDao" class="cn.itcast.ssh.user.dao.impl.UserImpl">

<!--注入SessionFactory -->

<property name="sessionFactory" ref=" sessionFactory "/>

</bean>

C.声明SessionFactory对应的Bean

<!-- SessionFactory -->

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<property name="configLocation" value="classpath:hibernate.cfg.xml"/>

</bean>

D.Hibernate模板默认没有自动的事务提交,因此需要手工添加事务,使用注解格式为业务层接口添加事务

@Transactional

public interface UserEbi {

public void add(UserModel um);

}

E.使用注解事务必须开启注释事务支持

applicationContext.xml文件中开启该注解驱动支持

<!-- 开启注释事务驱动 -->

<tx:annotation-driven transaction-manager=" txManager "/>

F.需要为注解驱动支持指定具体的事务管理器,使用Hibernate专用的事务管理器

<!-- txManager -->

<bean id="txManager"

 class="org.springframework.orm.hibernate3.HibernateTransactionManager">

<property name="sessionFactory" ref="sessionFactory"/>

</bean>

独立整合方式

hibernate.cfg.xml中的配置信息搬家到applicationContext.xml文件中

<!-- SessionFactory -->

<!-- 独立整合 -->

<!-- hibernate.cfg.xml文件中的配置信息搬家到这里 -->

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<!-- 数据库连接的配置 -->

<property name="dataSource" ref="dataSource"/>

<!-- 可选配置 -->

<property name="hibernateProperties">

<props>

<prop key="hibernte.dialect">org.hibernate.dialect.MySQLDialect</prop>

<prop key="hibernte.show_sql">true</prop>

<prop key="hibernte.format_sql">true</prop>

</props>

</property>

<!-- 资源注册 -->

<property name="mappingResources">

<list>

<value>cn/itcast/ssh/user/vo/UserModel.hbm.xml</value>

</list>

</property>

</bean>

<!-- 将数据库连接的配置转换为dataSource -->

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

<property name="driverClassName" value="com.mysql.jdbc.Driver"/>

<property name="url" value="jdbc:mysql://localhost:3306/ssh"/>

<property name="username" value="root"/>

<property name="password" value="root"/>

</bean>

独立整合常用资源注册的格式

格式二:

<property name="mappingDirectoryLocations">
     <list>
       <value>classpath:cn/itcast/ssh</value>
     </list>
 </property>

 

 

格式三:推荐使用此格式(通配符格式)

 <property name="mappingLocations">
     <list>
       <value>classpath:cn/itcast/ssh/*/vo/*Model.hbm.xml</value>
     </list>
 </property>

 

Hibernate模板类【理解】【应用】【重点】

1.HibernateTemplate使用方式

复制代码
//添加方法
public void add(User u){
  this.getHibernateTemplate().save(u);
}
//删除方法
public void delete(User u){
  this.getHibernateTemplate().delete(u);
}
//修改方法
public void update(User u){
  this.getHibernateTemplate().update(u);
}
//按uuid查询实体
public User getByUuid(Long uuid){
  return this.getHibernateTemplate().get(User.class,uuid);
}
//返回全部数据集合
public List<User> getAll(){
  return this.getHibernateTemplate().find("from User");
}
//返回分页集合数据
public List<User> getAll(int pageNum,int prePageNum){
  DetachedCriteria dc = DetachedCriteria.forClass(User.class);
  return this.getHibernateTemplate().findByCriteria(dc, (pageNum-1)*prePageNum, prePageNum);
}
复制代码

2.No Session问题

前提:

1.load方法是延迟加载的(所有存在延迟加载现象的操作)

2.业务逻辑层并没有加载该数据的延迟数据

3.表现层获取时事务已经关闭,所以该对象无法支持延迟加载,造成noSession问题

解决方案:(方案2更灵活)

1.lazy="false"

2.Hibernate提供了一个工具方法,用于将一个延迟加载的对象中的数据全部立即加载

Hibernate.initialize(u);

3.将事务开到表现层,添加OpenSessionInViewFilter

复制代码
<filter>
  <filter-name>openSessionInView</filter-name>
  <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>openSessionInView</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
复制代码

 

 

 

说明:

A. OpenSessionInView过滤器必须在struts2的核心过滤器之前开启,否则struts2获取数据时,仍然会出现Session已经关闭的现象

B.如果使用OpenSessionInView过滤器时,出现FlushModel相关的异常,换用如下过滤器,将事务设置为自动事务,而不是只读事务

复制代码
<filter>
       <filter-name>openSessionInView</filter-name>
       <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
       <init-param>
          <param-name>sessionFactoryBeanName</param-name>
          <param-value>sessionFactory</param-value>
       </init-param>
       <init-param>
            <param-name>singleSession</param-name>
            <param-value>true</param-value>           
       </init-param>
       <init-param>
            <param-name>flushMode</param-name>
         <param-value>AUTO</param-value>        
      </init-param>
</filter>
<filter-mapping>
  <filter-name>openSessionInView</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
复制代码

 


本文转自SummerChill博客园博客,原文链接:http://www.cnblogs.com/DreamDrive/p/6923888.html,如需转载请自行联系原作者

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值