zoukankan      html  css  js  c++  java
  • Sping

    [1].Sping 是什么

    Sping是一个开源的控制反转(Invarsion of Control IoC)和面向切面(AOP)的容器框架。
    它的主要目的是简化企业开发。


    [2].IOC控制反转

    public class PersonServiceBean{
    private PersonDao personDao = new PersonDaoBean();

    public void save(Person person){
    personDao.save(person);
    }
    }

    PersonDaoBean 是在应用内部创建及维护的。所谓的控制反转就是
    应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是有外部容器负责的。
    这样控制权就由应用转移到了外部容器,控制权的转移就是所谓发转。


    [3].依赖注入(Dependency Injection)
    当我们把依赖对象交给外部容器负责创建,那么PersonServiceBean类可以修改如下:
    public class PersonServiceBean(){
    private PersonDao personDao;
    //通过构造容器,让容器把创建好的依赖对象注入到PersonServiceBean中。
    //当然也可以使用setter方法进行注入
    public PersonServiceBean(PersonDao personDao){
    this.personDao= personDao;
    }

    public void save(Person person){
    personDao.save(person)
    }
    }

    所谓依赖注入就是指:在运行期间,由外部容器动态的将依赖对象注入到组件中。


    [4].为何要使用Spring
    在项目中引入Spring可以带来以下好处:
    1.减低组件之间的耦合度,实现软件各层之间的解耦。
    Controller-->Service-->DAO
    2.可以使用容器提供众多的服务。如:事件管理服务,消息服务等等。
    容器管理事务时,开发人员就不再需要手工控制事务,也不需要处理复杂的事务传播。
    3.容器提供单例模式支持,开发人员不再下需要自己编写实现代码。
    4.容器提供了AOP技术,利用它很容易实现如:权限拦截,运行期监控等功能。
    5.容器提供的众多辅助类,使用这些类能够加快应用的开发,如:JdbcTemplate
    HibernateTemplate。
    6.Spring对于主流的应用框架提供了集成支持,如:集成Hibernate,JPA、struts。
    这样便于应用的开发。


    [5].轻量级与重量级概念的划分
    Spring框架是一个轻量级的框架还是重量级的框架呢?
    判断一个框架是轻量级还是重量级,主要看它使用了多少服务,
    使用的服务越多,容器要为普通java对象做的工作就越多,
    必然会影响到应用的发布时间或者是运行性能。

    对于Spring容器,它提供了很多服务,但这些服务并不是默认都为应用打开的,
    应用需要某种服务,还需要指明使用该服务,如果应用使用的服务很少,
    如:只是用了spring的核心服务,那么此时应用属于轻量级的,如果应用使用了
    Spring提供的大部分服务,这时应用就属于重量级。


    [6]使用Spring需要jar文件
    distspring.jar
    libjakarta-commonscommons-logging.jar
    如果使用了切面编程(AOP),还需要下列jar文件
    lib/aspectj/aspectjweaver.jar和aspect.jar


    [7]Spring的配置文件模板
    <?xml version="1.0" encoding="UTF-8">
    <beans xmlns="" xmlns="" xsi:schemaLocation="">
    <bean>

    </bean>
    </beans>
    该配置模板可以从Spring的参考手册或spring的例子中得到,配置我呢见的
    取名可以任意,文件可以存放在任何目录写下,但考虑到通用性,一般放在
    类路径下。


    [8]实例化SPRING容器

    实例化Spring容器常用的两种方式:

    1.在类路径下寻找配置文件来实例化容器。
    ApplicationContext ctx = new
    ClassPathXmlApplicationContext(new String[]{"beans.xml"});

    2.在文件系统路径下寻找配置文件来实例化容器
    ApplicationContext ctx = new
    FileSystemXmlApplicationContext(new String[]{"d:\beans.xml"});

    考虑到应用的可移植性,建议使用第一种方式。spring的配置我呢见可以指定多个,
    可以通过Sring数组导入。

    PersonService.clsss
    public interface PersonService{
    public void save(){};
    }

    PersonServiceBean.clsss
    public class PersonServiceBean implements PersonService{
    public void save(){
    System.out.println("hello");
    };
    }

    <!--beans.xml-->
    <bean id="personService" clas"cn.soldier.service.imp.PersonServiceBean"></bean>

    Test.class

    @Test
    ApplicationContext ctx = new
    ClassPathXmlApplicationContext(new String[]{"beans.xml"});
    PersonService personService =(PersonService) ctx.getBean(personService);
    personService.save()


    [9]三种实例化Bean的方式
    1.使用类构造器实例化 99%
    <!--beans.xml-->
    <bean id="personService" clas"cn.soldier.service.imp.PersonServiceBean" />

    2.使用静态工厂方法实例化
    <!--beans.xml-->
    <bean id="personService2"
    clas"cn.soldier.service.imp.PresonServiceBeanFactory"
    factory-method="createPresonServiceBean" />

    <!--OrderFactory.class-->
    public class PresonServiceBeanFactory{
    public static PresonServiceBeanFactory createPresonServiceBean{
    return new PresonServiceBean();
    }
    }

    3.使用实例工厂方法实例化
    <!--beans.xml-->
    <bean id="personServiceFactory"
    class="cn.soldier.service.imp.PresonServiceBeanFactory" />
    <bean id="personService3" factory-bean="personServiceFactory"
    factory-method="createPresonServiceBean2" />

    <!--OrderFactory.class-->
    public class PresonServiceBeanFactory{
    public PresonServiceBean createPresonServiceBean2{
    return new PresonServiceBean();
    }
    }


    [10]bean的作用域
    singleton
    每个Spring Ioc容器中一个bean定义只有一个对象实例。默认情况下会在容
    器启动时初始化bean。但我们可以指定Bean节点的lazy-init="true"来延迟
    初始化bean,这时候,只有第一次获取bean才会初始化。
    如:
    <bean id="xxx" class="cn.soldier.OrderServiceBean" lazy-init="true" />
    如果你相对所有bean都应用延迟初始化。可以在根节点beans设置
    default-lazy-true。如下:
    <beans default-lazy-init="true">
    prototype
    每次从容器获取bean都是新的对象
    用法如下
    <bean id="xxx" clas"cn.soldier.OrderServiceBean" scope="prototype" />


    request
    session
    global session


    [11]指定bean的初始化方法和销毁方法

    <bean id="xxx" clas"cn.soldier.OrderServiceBean"
    init-method="init" destroy-method="close" />

    [12]注入依赖对象
    基本类型对象注入:
    <bean id="orderService" class="cn.soldier.OrderServiceBean">
    <constructor-arg index="0" type="java.lang.String" value="xxx" />//构造器注入
    <property name="name" value="zhao" /> 属性setter方式注入
    </bean>
    注入其他bean
    方式一:
    <bean id="orderDao" class="cn.soldier.OrderDaoBean" />
    <bean id="orderService" class="cn.soldier.OrderServiceBean">
    <property name="orderDao" value="orderDao" />
    </bean>
    方式二:(使用内部bean,但该bean不能被其他bean使用)
    <bean id="orderService" class="cn.soldier.OrderServiceBean">
    <property name="orderDao" >
    <bean id="orderDao" class="cn.soldier.OrderDaoBean" />
    </property>
    </bean>


    [13]集合类型的装配
    public class OrderServiceBean{
    private Set<String> sets = new HashSet<String>();
    private List<String> lists = new ArrayList<String>();
    private Properties<String> properties = new Properties();
    private Map<String,String> maps = new HasMap<String,String>();
    //这里省略属性的getter和setter方法
    }

    <bean id="orderService" class="cn.soldier.OrderServiceBean">
    <!--Set类型注入-->
    <property name="sets">
    <set>
    <value>第一个</value>
    <value>第二个</value>
    <value>第三个</value>
    </set>
    </property>
    <!--List类型注入-->
    <property name="lists">
    <list>
    <value>第一个</value>
    <value>第二个</value>
    <value>第三个</value>
    </list>
    </property>
    <!--Properties注入-->
    <property name="properties">
    <props>
    <prop key="key1">value1</prop>
    <prop key="key2">value2</prop>
    <prop key="key3">value3</prop>
    <props>
    </property>
    <!--Map类型注入-->
    <property name="maps">
    <map>
    <entry key="key1" value="value1" />
    <entry key="key2" value="value2" />
    <entry key="key3" value="value3" />
    </map>
    </property>
    </bean>


    [14]依赖注入
    使用构造器注入
    使用属性setter方法注入
    使用Field注入(用于注解方式)

    使用构造器注入
    <bean id="orderService" class="cn.soldier.OrderServiceBean">
    <constructor-arg index="0" type="java.lang.String" value="xxx" />//构造器注入
    <constructor-arg index="1" type="cn.soldier.OrderDao" ref="orderDao" />//构造器注入
    </bean>

    使用属性setter方法注入
    <bean id="orderService" class="cn.soldier.OrderServiceBean">
    <property name="id" value="1001" /> 属性setter方式注入
    <property name="name" value="liangxin" /> 属性setter方式注入
    </bean>


    注入依赖对象可以采用手工装配或自动装配,在实际应用中建议使用手工装配,
    因为自动装配会产生未知情况,开发人员无法预见最终装配结果

    1.手工装配依赖对象
    2.自动装配依赖对象


    [15]依赖注入--手工装配
    手工装配依赖对象,在这种方式中又有两种编程方式
    1.在xml配置文件中,通过bean节点配置。
    如下:
    <bean id="orderService" class="cn.soldier.service.OrderServiceBean">
    <constructor-arg index="0" type="java.lang.String" value="xxx" />//构造器注入
    <property name="name" value="zhao" /> 属性setter方式注入
    </bean>
    2.在java代码中使用[@Autowired]或[@Resource]注解方式进行装配。但我么们需要先
    在xml文件中配置以下信息:
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsl="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsl:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <context:annotation-config />
    </beans>
    这个配置隐式注册了多个对注释进行解析处理的处理器:
    AutowiredAnnotationBeanPostProcessor,
    CommonAnnotationBeanPostProcessor,
    PersistenceAnnotationBeanPostProcessor,
    RequiredAnnotationBeanPostProcessor
    注:[@Resource]注解在spring安装目录的libj2eecommon-annotations.jar

    在java代码中使用 [@Autowired] 、 [@Resource] 方式进行装配,这两个注释的区别是
    @Autowired 默认按类型装配
    @Resource 默认使用安名称装配,当找不到与名称匹配的bean时才会安类型转配

    例子如下:
    @Autowired //用于字段上
    private PersonDao personDao;
    @Autowired //用于属性的setter方法上
    public void setOrderDao(OrderDao orderDao){
    this.orderDao = orderDao;
    }
    @Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在。
    如果允许null值,可以设置它的required属性为false。
    如果想使用按名称装配,可以结合 [@Qualifier] 注解一起使用.
    例子如下:
    @Autowired @Qualifier["personDaoBean"]
    private PersonDao personDao;

    @Resource 注解和 @Autowirde 注解一样,也是可以标注在字段或属性的setter
    方法上,但它默认按名称装配。名称可以通过 @Resource 的name属性指定,如果
    没有指定name属性,当注解在字段上,即默认取字段的名称作为bean名称寻找依赖对象
    当注解在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。
    @Resource(name="personDaoBean")
    privte PersonDao personDao; //用于字段上

    注意: @Resource 如果没有指定属性名,并且按照默认名称仍然找不到依赖对象时,
    @Resource注解会回退到按类型匹配,但一旦指定了name属性,就只能按名称装配了。


    [16]依赖注入--自动装配依赖对象
    对于自动装配,大家了解一下就可以了。
    例子如下
    <bean id="" class="" autowire="byType" />

    autowire属性取值如下:
    byType:按类型匹配,可以根据属性的类型,在容器中寻找跟该类型匹配的bean。
    如果发现多个,那么将会抛出异常。如果没有找到,那么属性值为null。
    byName:按名称装配,可以根据属性的名称,在容器中寻找跟该属性名相同的bean。
    如果没有找到,那么属性值为null。
    constructor:constructor与byType方式相似,不同之处在于它应用构造器参数。
    如果没有找到与构造器参数类型一直的bean,那么将会抛出异常。
    autodetect:通过bean类的自省机制(introspection)来决定使用constructor还是
    byType方式进行自动装配,<!--如果发现有默认的构造器,那么将使用byType方式-->


    [16]通过在classpath自动扫描方式把组件纳入spring容器中管理

    前面的例子我们都是使用XML的bean定义配置组件的。在一个稍大的项目中,通常会
    有上百个组件,如果这些组件采用xml的bean定义来配置,显然会增加配置文件的体积
    而且查找和维护起来也不太方便。使用自动扫描机制,它可以在类路径下寻找标注了
    @Component @Service @Controller @Repository注解的类,并把这些类纳入进spring
    容器中管理。它的作用和xml文件使用bean节点配置组件是一样的。
    要使用自动扫描机制,我们需要设置一下配置信息

    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsl="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsl:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <context:component-scan base-package="cn.soldier" />
    <!--包含了这个处理器 <context:annotation-config /> -->
    </beans>
    其中base-package为需要扫描的包(包含子包)

    @Component 泛指组件,当组件不好归类的时候,可以使用这个注释进行标注
    @Service 用于标志业务层组件
    @Controller 用于标注控制层组件(如struts的action)
    @Repository 用于标注数据访问组件 即DAO层

    @Service("xxxx")
    改名为xxxx
    public class OrderServiceBean{

    }

    @Service @Scope("proptotype")
    改为原型作用域,默认是单例
    public class OrderServiceBean{

    }

    @PostConstruct //初始化注解
    public void init(){
    }

    @PreDestory //注销注解
    public void destory(){
    }

    [17]AOP中的概念
    Aspect(切面):指横切性关注点的抽象。即为切面,它与类相似。只是两者的关注点
    不一样,类是读物体特征的抽象,而切面是横切性关注点是抽象。

    Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在Spring中,这些点值得是
    方法,因为spring只支持方法类型的连接点,实际上joinpoint还是field或类构造器

    Pointcut(切入点):所谓切入点是我们对那些joinpoint进行拦截的定义
    Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知,通知分
    前置通知,后置通知,异常通知,最终通知,环绕通知

    Target(目标对象):代理的目标对象

    Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程
    IntroDuction(引入):在不修改类代码的前提下,Introduction可以运行期为类动态的
    添加一些方法或field

    [18]使用Spring进行面向切面编程
    要进行aop编程,首先我们要在Spring的配置文件中导入aop命名空间


    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsl="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/aop"
    xsl:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">


    </beans>

    Spring 提供了两种面向切面使用方式,实际工作中我们可以选用其中一种,
    1.基于XML配置方式的AOP开发

    2.基于注解方式的AOP开发

    [19]基于注解方式声明切面
    1.首先启动 @AspertJ注解的支持

    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsl="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsl:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

    <aop:aspectj-autoproxy />
    <bena id="rderservise" class="" />
    <bena id="rderservise" class="" />
    </beans>

    2。定义好切面

    3.交给Spring管理
    <bena id="myInterceptor" class="cn.soldier.service.MyInterceptor" />

    //定义切面
    @Aspect
    public class LogPrint{
    @Pointcut("ececution(* cn.soldier.service..*.*(..))") //
    private void anyMethod{}//声明一个切入点
    @Before("anyMethod() && args(userName)")//定义前置通知
    public void doAccessCheck(String userName){
    }
    @AfterReturning(pointcut="anyMethod()",returning="revalue")//定义后置通知
    public void doReturnCheek(String revalue){
    }
    @AfterThroving(pointcut="anyMethod()",throwing="ex")//定义例外通知
    public void doExceptionAction(Exception ex){
    }
    @After("anyMethod()")//定义最终通知
    public void doReleaseAction(){
    }
    @Around("anyMethod()")//环绕通知
    public Object doBasicProfiling(ProceedingJoinPotint pjp) throws Throwable{
    //if(){//判断用户是否有权限
    Object result = pjp.proceed();
    //}
    return result;
    }
    }

    @Pointcut"ececution(* cn.soldier.service..*.*(..))
    ececution //执行
    (
    *//返回值类型
    cn.soldier.service//哪个包
    ..//子包也拦截
    *//哪个类
    .*//哪个方法,
    (..)//哪些参数
    )
    这里表示的是对于cn.soldier.service包及其子包下的所有
    类的任意返回值的所有方法的进行拦截。


    [19]基于xml配置方式声明切面

    //定义切面

    <bean id="orderservice" class="cn.soldier.service.OrderServiceBean" />
    <bean id="log" class="cn.soldier.service.LogPrint" />
    <aop:config>
    <aop:aspect id="myaop" ref="log">
    <aop:pointcut id="mycut" experssion="execution(* cn.soldier.service..*.*(..))" />
    <aop:before pointcut-ref="mycut" method="doAccessCheck" />
    <aop:after-returning pointcut-ref="mycut" method="doReturnCheck" />
    <aop:after-throwing pointcut-ref="mycut" method="doExceptionAction" />
    <aop:after pointcut-ref="mycut" method="doReleaseAction" />
    <aop:around pointcut-ref="mycut" method="doBasicProfiling" />
    </aop:aspect>
    </aop:cinfig>

    public class LogPrint{
    public void doAccessCheck(String userName){
    System.out.println("前置通知");
    }
    public void doReturnCheck(){
    System.out.println("后置通知");
    }
    public void doReleaseAction(){
    System.out.println("最终通知");
    }
    public void doExceptionAction()
    System.out.println("例外通知");
    }
    public Object doBasicProfiling(ProceedingJoinPotint pjp) throws Throwable{
    System.out.println("环绕通知");
    //if(){//判断用户是否有权限
    Object result = pjp.proceed();
    //}
    return result;
    }
    }
    [20]Spring--JDBC 组合开发

    使用Spring+JDBC集成步骤如下:
    1.配置数据库,如:
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSpource"
    destroy-method="close"><!--destroy-method="close"设置为单例-->
    <property name="driverClassNamme" value="org.gjt.mm.mysql.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/soldier?
    useUnicode=true&amp;characterEncoding-UTF-8" />
    <property name="username" value="root" />
    <property name="password" value="123456"
    <!--连接池启动时的初始值-->
    <property name="initialSize" value="1" />
    <!--连接池的最大值-->
    <property name="maxActive" value="500" />
    <!--最大空闲值,当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释
    放一部分一直减少到maxIdle为止-->
    <property name="maxIdle" value="2" />
    <!--最小空闲值,当经空闲的连接邵谊阀值时,连接池就会申请一些连接,
    以免洪峰来时来不及申请-->
    <property name="minIdle" value="1" />
    </bean>
    2.配置事务
    配置事务时,需要在xml配置文件中引入用于声明事务的tx命名空间,
    事务的配置方式有两种:注解方式和基于XML配置方式。

    [21]使用注解方式配置事务

    1.声明tx命名空间
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsl="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsl:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    </beans>

    2.配置bean
    <bean id="txManager" class="org.springframework.jdbc.datasource
    .DataSorceTransaction.Manager">
    <property name="dataSource" ref="dataSource" /><!--配置数据源-->
    </bean>

    3.采用组件
    <!--采用 @Transaction注解方式使用事务-->
    <tx:annotationn-driver transaction-manager="txManager" /><!-- transaction-manager 配置事务管理器-->


    PersonServiceBean.class
    @Service @Transactional
    public class PersonServiceBean implements PersonService{
    }

    [22]使用JdbcTemplate获取一条记录
    @Service @Transaction
    public class PersionServiceBean implements PersonService{
    Private JdbcTemplate jdbcTemplate;
    @Resource
    public void setDataSourse(DataSource dataSource){
    this.jdbcTemplate = new JdbcTemllate(dataSource);
    }
    public Person getPerson(Integer id){
    RowMaooer rowMapper = new RowMapper(){
    public Object mapRow(ResuleSet rs,int rowNum) throws SQLException{
    Person person = new Person();
    person.setId(rs.getInt("id"));
    person.getName(re.getString("name"));
    return person;
    }
    };
    String sql ="SELECT * FROM person WHERE id=?"
    return (Person)jdbcTemplate.queryForObject(sql,new Object[]{id},
    new int[]{java.sql.Types.INTGER},rowMapper);
    }
    }

    [23]使用JdbcTemplate获取多条记录
    @Service @Transactional
    public class PersonServiceBean implements PersonService{
    pirvate JdbcTemplate jdbcTemplate;
    @Resource
    public void setDataSource(DataSource dataSource){
    this.jdbcTemplate = new JdbcTempleate(dataSource);
    }
    public List<Person> getPersons(){
    RowMaooer rowMapper = new RowMapper(){
    public Object mapRow(ResuleSet rs,int rowNum) throws SQLException{
    Person person = new Person();
    person.setId(rs.getInt("id"));
    person.getName(re.getString("name"));
    return person;
    }
    };
    String sql = "SELCET * FROM person";
    return jdbcTemplate.query(sql,rowMapper);

    }
    }

    <!--jdbc.properties-->
    driverClassNamme=org.gjt.mm.mysql.Driver
    url=jdbc:mysql://localhost:3306/soldier?useUnicode=true&characterEncoding=UTF-8" />
    username=root
    password=123456
    initialSize=1
    maxActive=500
    maxIdle=2
    minIdle=1

    bean.xml
    使用属性占位符配置上面的数据源

    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsl="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsl:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <context:property-placeholder location ="classpath: jdbc.properties" />
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSpource"
    destroy-method="close"><!--destroy-method="close"设置为单例-->
    <property name="driverClassNamme" value="${driverClassNamme}" />
    <property name="url" value="${url}" />
    <property name="username" value="${username}" />
    <property name="password" value="${password}"
    <!--连接池启动时的初始值-->
    <property name="initialSize" value="${initialSize}" />
    <!--连接池的最大值-->
    <property name="maxActive" value="${maxActive}" />
    <!--最大空闲值,当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释
    放一部分一直减少到maxIdle为止-->
    <property name="maxIdle" value="${maxIdle}" />
    <!--最小空闲值,当经空闲的连接邵谊阀值时,连接池就会申请一些连接,
    以免洪峰来时来不及申请-->
    <property name="minIdle" value="${minIdle}" />
    </bean>

    <bean id="txManager" class="org.springframework.jdbc.datasource
    .DataSorceTransaction.Manager">
    <property name="dataSource" ref="dataSource" /><!--配置数据源-->
    </bean>
    <tx:annotationn-driver transaction-manager="txManager" />
    <!-- transaction-manager 配置事务管理器-->

    </beans>

    [24]事务传播属性
    REQUIRED:
    特务方法需要在一个事务中运行。如果方法运行时,已经处在一个事务中,那么
    加入该事务,否则为自己创建一个事务。
    NOT_SUPPORTED:
    声明方法不需要事务,如果方法没有关联到一个事务中,容器不会为它开启事务,如果
    方法在一个事务中被调用,该事务会被挂起,在方法调用结束后,
    原先的事务便会恢复执行。
    REQUIRESNEW:
    属性表明不管是否存在事务,业务方法总会为自己发起一个新的事务,如果方法已
    经运行在一个事务中,则原先的事务会被挂起,新的事务会被创建,直到方法执行结束
    新的事务才算结束,原先的事务才会恢复执行。
    MANDATORY:
    该属性指定业务防范只能在一个已经存在的事务中执行,业务方法不能发表自己的事务。
    如果业务方法在事务范围外被调用,则方法在没哟偶事务的环境下执行行。
    SUPPORTS:
    这一书屋属性表明。如果业务方法在某个事务范围内被调用,则方法称为该是唔的一部分,
    如果业务方法在事务范围外被调用,则方法在没有事务的环境下执行。
    Never:
    指定业务放大绝对不能再事务范围内执行,如果业务方法在某个事务中执行,容器会抛出
    例外,只有业务方法没哟偶关联到任何事务,才能正常执行。
    NESTED:
    如果一个活动的事务存在,则运行在一个嵌套的十五中,如果没有活动事务则按
    REQUIRDE属性执行,他使用了一个单独的事务。这个事务用用多个回滚的保存掉,内部
    事务的回滚不会对外部事物造成影响,它只对DataSourceTransactionManager事务管理器
    起效。


    @Transactional(noRollbackFor=RuntimeException.class) //即使发生异常也不回滚
    public void delete(Integet personid) throws Exception{
    throws new RuntimeException("运行期例外");
    }
    @Transactional(rollbackFor=RuntimeException.class) //发生异常回滚
    public void delete(Integet personid) throws Exception{
    }
    @Transactional(propagetion=Propagation.NOT_SUPPPRTED)//注明不需要事务管理
    public Person getPerson(Integet personId){
    }

    [25]事务传播属性NESTED介绍

    @Resource OtherService otherService;

    public void xxx(){
    String sql ="UPDATE person SET name='888' WHERE id=1";
    stmt.executeUpdate(sql);
    sql = "UPDATE person SET name='222' WHERE id=2";
    stmt.executeUpdate(sql);
    otherService.update();//OtherService的update方法的事务传布属性为NESTED
    sql ="DELETE FROM person WHERE id=9";
    stmt executeUpdate(sql);

    }
    上面 xxx()的内部执过程
    public void xxx(){
    Connection conn = null;
    try{
    conn.setAutoCommit(false);
    Statement stmt =conn.createStatement();
    String sql ="UPDATE person SET name='888' WHERE id=1";
    stmt executeUpdate(sql);

    SavePoint savapoint = conn.setSavepotion();//Spring容器生成

    try{
    String temp = "UPDATE person SET name='222' WHERE id=2";
    conn.createStatement().executeUpdate(sql);
    }catch(Exception ex){

    conn.rollvack(savepoint);//Spring容器生成

    }
    sql ="DELETE FROM person WHERE id=9";
    stmt executeUpdate(sql);
    }catch(Exception ex){

    conn.rollvack(); //Spring容器生成

    }finally{
    try{
    if(null != conn && !conn.IsClose())
    conn.close();
    }catch(SQLException e){
    e.printStackTrece();
    }
    }
    }

    [26]数据库提供的四种事务隔离级别
    数据库系统提供了四种事务隔离级别供用户选择,不同的隔离级别采用不同的锁类型来
    实现,在四种隔离级别中,Serializble的隔离级别最高,Read Uncommited的隔离级别
    最低,大多数数据库默认的隔离级别为Read Commited如SQLSERVER 2000。当然也有少部分
    的隔离级别是Repeatable Read,如 MYSQL
    Read Uncommited 读未提交数据(会出现脏读,不可重复读和幻读)
    Read Commited 读已提交的数据(会出现不可重复读和幻读)
    Repeatable Read 可重复读(会出现幻读)
    Serializble 串行化

    脏读:就是一个事务读取到另一个事务为提交的更新数据。
    不可重复读:就是在一个事务中,多次读取同一数据返回的结果有所不同。
    换句话说就是,后续读取可以读到另一事务已提交的数据。
    可重复读:就是在同一个事务中,多次读取数据时,能够保证所读取数据时一样的,
    也就是后续读取不能读到另一事务已提交的更新数据。
    幻读:就是一个事务读取到另一事务已提交的insert数据。

    [27]基于XML方式配置事务
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSoource">
    </bean>
    <!--配置aop,拦截所有方法cn.soldier.servlce..*.*(..),交给txAdvice事务通知处理-->
    <aop:config>
    <aop:pointcut id="transactionPointcut" expression="execution(* cn.soldier.servlce..*.*(..))"/>
    <aop:adivsor adiver-ref="txAdvice" pointcut-ref="transactionPointcut" />
    </aop:config>

    <tx:advice id="txAdvice" transaction-manager="txManager" />
    <tx:attributes>
    <!--如果拦截以get开头的方法,不需要事务 -->
    <tx:method name="get*" read-only="true" propagaction="NOT_SUPPORTED" />
    <!--其他方法,使用事务的默认行文,数据库隔离级别使用数据库的默认隔离级别 -->
    <tx:method name="*" />
    </tx:attributes>
    </tx:advice>

  • 相关阅读:
    Python pyspider 安装与开发
    Shell curl 和 wget 使用代理IP
    米扑代理示例(mimvp-proxy-demo)
    图片加载失败如何替换成默认图片
    Node-mongodb链接数据库函数的封装
    移动端拼图效果实现
    JS调用百度地图API获取地理位置
    The Begin
    Matlab(Client)和Python(Server)进行TCP通信
    ubuntu如何有效扩容根目录的记录(实践有效ubuntu20.0版本)
  • 原文地址:https://www.cnblogs.com/lhy_2011/p/4025932.html
Copyright © 2011-2022 走看看