Spring

什么是Spring

  Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。

Spring:SE/EE开发一站式框架.

  WEB层:SpringMVC

  Service层:Spring的Bean管理,Spring的声明式事务

  Dao层:Spring的JDBC模板,Spring的ORM模块

为什么学习Spring

 

特点

 

1.方便解耦,简化开发

  通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。

2.AOP编程的支持

  通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。

3.声明式事务的支持

  在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。

4.方便程序的测试

  可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。

5.方便集成各种优秀框架

  Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。

6.降低Java EE API的使用难度

  Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。

7.Java 源码是经典学习范例

  Spring的源码设计精妙、结构清晰、匠心独运,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。Spring框架源码无疑是Java技术的最佳实践范例。如果想在短时间内迅速提高自己的Java技术水平和应用开发水平,学习和研究Spring源码将会使你收到意想不到的效果。

 

 

Spring的版本

  Spring3.xSpring4.x

Spring的入门(IOC)

什么IOC

  IOC: Inversion of Control(控制反转)

  控制反转:将对象的创建权反转给(交给)Spring

下载Spring的开发包

 

  官网http://spring.io/

 

解压Spring的开发包

 

 

  1. docs Spring的开发规范和API
  2. libs Spring的开发的jar和源码
  3. schema Spring的配置文件的约束 

创建web项目,引入jar

创建接口和类

 1 /**
 2  * 用户管理DAO层接口
 3  * @author Administrator
 4  *
 5  */
 6 
 7 public interface UserDao {
 8     
 9     public void save();
10     
11 }
 1 /**
 2  * 用户管理Dao层的实现类
 3  * @author Administrator
 4  *
 5  */
 6 
 7 public class UserDaoImpl implements UserDao {
 8 
 9     private String name;
10     
11     
12     
13     public String getName() {
14         return name;
15     }
16 
17 
18 
19     public void setName(String name) {
20         this.name = name;
21     }
22 
23 
24 
25     public void save() {
26         System.out.println("UserDaoImpi执行了................"+name);
27     }
28 
29     
30 
31 }

 问题:

   如果底层的实现切换了,需要修改源代码,能不能不修改程序源代码对程序进行扩展?

将实现类交给Spring管理

  在spring的解压路径下spring-framework-4.2.4.RELEASE\docs\spring-framework-reference\html\xsd-configuration.html

1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans     xmlns="http://www.springframework.org/schema/beans"
3         xmlns:p="http://www.springframework.org/schema/p"
4         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
6      
7     <!-- Spring的入门配置 -->
8         <bean id="UserDao" class="com.zmy.spring.demo1.UserDaoImpl"> </bean>

编写测试类

 1 import org.junit.Test;
 2 import org.springframework.context.ApplicationContext;
 3 import org.springframework.context.support.ClassPathXmlApplicationContext;
 4 
 5 /**
 6  * Spring的入门
 7  * @author Administrator
 8  *
 9  */
10 
11 public class SpringDemo01 {
12 
13     @Test
14     //Spring的方式的调用
15     public void demo01() {
16         //创建spring工厂
17         ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
18         UserDao userDao = (UserDao) applicationContext.getBean("UserDao");
19         userDao.save();
20         
21     }
22     
23 }

IOCDI*****

  IOC:控制反转,将对象的创建权反转给了Spring

  DI:依赖注入,前提必须有IOC的环境,Spring管理这个类的时候将类的依赖的属性注入(设置)进来。

  面向对象的时候

 1   依赖
 2 
 3 Class A{
 4 
 5  
 6 
 7 }
 8 
 9  
10 
11 Class B{
12 
13   public void xxx(A a){
14 
15  
16 
17   }
18 
19 }
20 
21   继承:is a
22 
23 Class A{
24 
25  
26 
27 }
28 
29 Class B extends A{
30 
31  
32 
33 }
34 
35   聚合:has a

Spring的工厂类

Spring工厂类的结构图

  ApplicationContext继承BeanFactory

BeanFactory:老版本的工厂类

  BeanFactory:调用getBean的时候,才会生成类的实例。

ApplicationContext:新版本的工厂类

  ApplicationContext:加载配置文件的时候,就会将Spring管理的类都实例化。

  ApplicationContext有两个实现类

ClassPathXmlApplicationContext:加载类路径下的配置文件

  FileSystemXmlApplicationContext :加载文件系统下的配置文件

 

Spring的配置

 XML的提示配置

  Schema的配置

 

Bean的相关的配置

  <bean>标签的idname的配置

     id :使用了约束中的唯一约束。里面不能出现特殊字符的。

     name :没有使用约束中的唯一约束(理论上可以出现重复的,但是实际开发不能出现的)。里面可以出现特殊字符。

    SpringStruts1框架整合的时候

    <bean name=”/user” class=””/>

   Bean的生命周期的配置(了解)

    init-method :Bean被初始化的时候执行的方法

    destroy-method :Bean被销毁的时候执行的方法(Bean是单例创建,工厂关闭)

  Bean的作用范围的配置(重点)

    scope Bean的作用范围

    singleton:默认的,Spring会采用单例模式创建这个对象。

    prototype:多例模式。(Struts2Spring整合一定会用到)

    request :应用在web项目中,Spring创建这个类以后,将这个类存入到request范围中。

    session :应用在web项目中,Spring创建这个类以后,将这个类存入到session范围中。

     globalsession :应用在web项目中,必须在porlet环境下使用。但是如果没有这种环境,相对于session

 

SpringBean管理(XML方式)

  SpringBean的实例化方式(了解)

Bean已经都交给Spring管理,Spring创建这些类的时候,有几种方式:

  无参构造方法的方式(默认)

 

  编写配置

 

实例工厂实例化的方式

  Bean3的实例工厂

 

  配置

 

  

Spring的属性注入

构造方法的方式的属性注入

  构造方法的属性注入

1 <!-- 构造方法的方式 -->
2      <bean id="Car2" class="com.zmy.spring.demo1.Car2">
3          <constructor-arg name="name" value="奔驰" />
4          <constructor-arg name="price" value="80000"/>
5      </bean>

Set方法的方式的属性注入

  Set方法的属性注入

<!-- set方法的方式 -->
    <bean id="Car" class="com.zmy.spring.demo1.Car">
        <property name="name" value="宝马"/>
        <property name="price" value="10000"/>
    </bean>

P名称空间的属性注入(Spring2.5以后)

  通过引入p名称空间完成属性的注入:

  写法:

    普通属性 p:属性名=

    对象属性 p:属性名-ref=

  P名称空间的引入

 

<?xml version="1.0" encoding="UTF-8"?>
<beans     xmlns="http://www.springframework.org/schema/beans"
        xmlns:p="http://www.springframework.org/schema/p"
        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">

  使用p名称空间

 

1 <bean id="Car" class="com.zmy.spring.demo1.Car" p:name="杨戬"  p:price="18888"></bean>    
2     <bean id="Car3" class="com.zmy.spring.demo1.Car3"  p:name="花木兰" p:Car-ref="Car"></bean>

SpEL的属性注入(Spring3.0以后)

  SpELSpring Expression LanguageSpring的表达式语言。

    语法:

       #{SpEL}

 

 1 <!-- Spel的属性注入 -->
 2     <bean id="User" class="com.zmy.spring.demo1.User"></bean>
 3     <bean id="Car" class="com.zmy.spring.demo1.Car"  >
 4         <property name="name"  value="#{User.name}"></property>
 5         <property name="price"  value="#{User.calculatorPrice()}"></property>
 6     </bean>
 7     <bean id="Car3" class="com.zmy.spring.demo1.Car3" >
 8         <property name="name"  value="#{'花木兰'}"></property>
 9         <property name="Car"  value="#{Car}"></property>
10     </bean> 

集合类型属性注入(了解)

  配置

 

 1 <!-- spring 的集合注入================== -->
 2         <!-- 注入数组类型 -->
 3     <bean id="collectionBean" class="com.zmy.spring.demo2.CollectionBean">
 4          <!-- 数组类型 -->
 5         <property name="arrs">
 6             <list>
 7                 <value>诸葛亮</value>
 8                 <value>貂蝉</value>
 9                 <value>小乔</value>
10             </list>
11         </property>
12        <!-- 注入list集合 -->
13         <property name="list">
14             <list>
15                 <value>诸葛亮</value>
16                 <value>貂蝉</value>
17                 <value>小乔</value>
18             </list>
19         </property>
20         <!-- 注入set集合 -->
21         <property name="set">
22             <set>
23                 <value>诸葛亮</value>
24                 <value>貂蝉</value>
25                 <value>小乔</value>
26             </set>
27         </property>
28           <!-- 注入Map集合 -->
29         <property name="map">
30             <map>
31                 <entry key="aaa" value="111"/>
32                 <entry key="bbb" value="222"/>
33                 <entry key="ccc" value="333"/>
34             </map>
35         </property>
36     </bean>                        

Spring的分模块开发的配置

  分模块配置

   在加载配置文件的时候,加载多个

 

 

  在一个配置文件中引入多个配置文件

 

 代码实现

  1.创建数据库和表

  2.创建web项目,引入jar

    引入struts2的开发的jar

    引入struts2的配置文件

   web.xml

 

  struts.xml

 

引入页面

  编写Action

 

  配置Action

 

  修改页面提交到Action

 

   编写Actionsave方法

    不在Action中直接创建Service,将Service交给Spring管理。

    创建Service接口和实现类

 

 

  引入Spring的环境

    1.引入jar

    2.引入配置文件

  将Service交给Spring

 

Action中调用Service

 

编写DAO并且完成配置

  编写DAO的接口和实现类

 

 

 

  将DAO交给Spring管理

 

Service中使用DAO

 

问题描述

  程序问题

    每次请求都会创建一个Spring的工厂,这样浪费服务器资源,应该一个项目只有一个Spring的工厂。

    在服务器启动的时候,创建一个Spring的工厂。

    创建完工厂,将这个工厂类保存到ServletContext中。

    每次使用的时候都从ServletContext中获取。

  *****使用ServletContextListener

  监听ServletContext对象的创建和销毁。

  解决方案:使用Spring核心监听器ContextLoaderListener(整合web项目)

    引入jar

    spring-web.jar

 

    配置监听器

 

    在Action中获取工厂

 

 

IOC的XML和注解开发比较

适用场景

   XML:可以适用任何场景.

    结构清晰,维护方便.

  注解:有些地方用不了,这个类不是自己提供的.

    开发方便.

XML和注解整合开发

  XML管理Bean,注解完成属性的注入.

 

Spring的IOC注解入门(XML方式)

1.导入jar.包

 

 2.创建applicationContext.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<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">

    <!-- spring的IOC注解入门 -->
    <!-- 使用IOC的注解开发,配置组件扫描(那些包下使用的注解开发) -->
    <!-- 扫描是为了扫描类上的注解 -->
    <context:component-scan base-package="com.zmy.spring"/>

    <bean id="productService" class="com.zmy.spring.demo3.ProductService" >
        <property name="productDao" ref="productDao"/>
        <property name="orderDao" ref="orderDao"/>
    </bean>


    <bean id="productDao" class="com.zmy.spring.demo3.ProductDao" ></bean>
    <bean id="orderDao" class="com.zmy.spring.demo3.OrderDao" ></bean>


</beans>

创建ProductService.java

package com.zmy.spring.demo3;

import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @Auther: zmy
 * @create:2019-04-08-9:50
 */
@Service(value = "productService")
public class ProductService {
    //注入对象属性
    @Resource(name = "productDao")
    private ProductDao productDao;
    @Resource(name = "orderDao")
    private OrderDao orderDao;

    public void setProductDao(ProductDao productDao) {
        this.productDao = productDao;
    }

    public void setOrderDao(OrderDao orderDao) {
        this.orderDao = orderDao;
    }

    public void save() {
        System.out.println("ProductService中的save方法执行了...........");
        productDao.save();
        orderDao.save();
    }

}

创建ProductDao.java

package com.zmy.spring.demo3;

/**
 * @Auther: zmy
 * @create:2019-04-08-9:52
 */
public class ProductDao {
    public void save() {
        System.out.println("ProductDao中的save方法执行了...........");
    }
}

创建OrderDao.java

package com.zmy.spring.demo3;

/**
 * @Auther: zmy
 * @create:2019-04-08-9:52
 */
public class OrderDao {
    public void save() {
        System.out.println("OrderDao中的save方法执行了...........");
    }
}

创建测试类SpringTest3.java

package com.zmy.spring.demo3;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Auther: zmy
 * @create:2019-04-08-9:59
 */
public class SpringTest3 {
    @Test
   public void demo01() {
       ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
       ProductService productService = (ProductService) applicationContext.getBean("productService");
       productService.save();
   }
}

 

 XML和注解整开发

<?xml version="1.0" encoding="UTF-8"?>
<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">

    <!-- spring的IOC注解入门 -->
    <!-- 使用IOC的注解开发,配置组件扫描(那些包下使用的注解开发) -->
    <!-- 扫描是为了扫描类上的注解 -->
   <!-- <context:component-scan base-package="com.zmy.spring"/>-->

    <!--没有扫描情况下,使用属性的属性注入的注解 :@Resource @Value @Autowired @Qualifier -->
    <context:annotation-config/>

    <bean id="productService" class="com.zmy.spring.demo3.ProductService" >
       <!-- <property name="productDao" ref="productDao"/>
        <property name="orderDao" ref="orderDao"/>-->
    </bean>


    <bean id="productDao" class="com.zmy.spring.demo3.ProductDao" ></bean>
    <bean id="orderDao" class="com.zmy.spring.demo3.OrderDao" ></bean>


</beans>
package com.zmy.spring.demo3;

import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @Auther: zmy
 * @create:2019-04-08-9:50
 */
@Service(value = "productService")
public class ProductService {
    //注入对象属性
    @Resource(name = "productDao")
    private ProductDao productDao;
    @Resource(name = "orderDao")
    private OrderDao orderDao;

   /* public void setProductDao(ProductDao productDao) {
        this.productDao = productDao;
    }

    public void setOrderDao(OrderDao orderDao) {
        this.orderDao = orderDao;
    }*/

    public void save() {
        System.out.println("ProductService中的save方法执行了...........");
        productDao.save();
        orderDao.save();
    }

}

Bean的生命周期注解方式(了解)

类的注解和属性的注解

 

 

 

 

Bean的作用范围的配置(重点)

    scope :Bean的作用范围

    singleton:默认的,Spring会采用单例模式创建这个对象。

    prototype:多例模式。(Struts2和Spring整合一定会用到)

    request :应用在web项目中,Spring创建这个类以后,将这个类存入到request范围中。

    session :应用在web项目中,Spring创建这个类以后,将这个类存入到session范围中。

     globalsession :应用在web项目中,必须在porlet环境下使用。但是如果没有这种环境,相对于session

 

Spring的AOP(理解)

AOP - 面向切面编程 

  在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

  AOP分为JDK动态代理和Cglib动态代理

JDK动态代理

Cglib动态代理

  是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Hibernate支持它来实现PO(Persistent Object 持久化对象)字节码的动态生成。

  第三方开源代码生成类库,动态添加类的属性和方法.

 

 

 

 

 

 

 

Junit 和spring集合测试

 

 

切面类

 

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">


    <!--配置目标对象:被增强的对象-->
    <bean id="productDao" class="com.zmy.spring.demo3.ProductDaoImpl"/>

    <!--将切面类及交给spring管理-->
    <bean id="myAspect" class="com.zmy.spring.demo3.MyAspectJXML"/>

    <!--通过AOP的配置完成对目标类产生代理-->
    <aop:config>
        <!--表达式配置哪些类哪些方法需要进行增强-->
        <aop:pointcut id="pointcut1" expression="execution(* com.zmy.spring.demo3.ProductDaoImpl.save(..))"/>

        <!--配置切面类-->
        <aop:aspect ref="myAspect">
            <aop:before method="checkPri" pointcut-ref="pointcut1"/>
        </aop:aspect>
    </aop:config>



</beans>

 

 

<?xml version="1.0" encoding="UTF-8"?>
<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">


    <!--配置目标对象:被增强的对象-->
    <bean id="productDao" class="com.zmy.spring.demo3.ProductDaoImpl"/>

    <!--将切面类及交给spring管理-->
    <bean id="myAspect" class="com.zmy.spring.demo3.MyAspectJXML"/>

    <!--通过AOP的配置完成对目标类产生代理-->
    <aop:config>
        <!--表达式配置哪些类哪些方法需要进行增强-->
        <aop:pointcut id="pointcut1" expression="execution(* com.zmy.spring.demo3.ProductDaoImpl.save(..))"/>
        <aop:pointcut id="pointcut2" expression="execution(* com.zmy.spring.demo3.ProductDaoImpl.delete(..))"/>
        <aop:pointcut id="pointcut3" expression="execution(* com.zmy.spring.demo3.ProductDaoImpl.update(..))"/>
        <aop:pointcut id="pointcut4" expression="execution(* com.zmy.spring.demo3.ProductDaoImpl.find(..))"/>

        <!--配置切面类-->
        <aop:aspect ref="myAspect">
            <!--前置通知-->
            <aop:before method="checkPri" pointcut-ref="pointcut1"/>
            <!--后置通知-->
            <aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"/>
            <!--环绕通知-->
            <aop:around method="around" pointcut-ref="pointcut3"/>
            <!--异常抛出通知-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
            <!--最终通知-->
            <aop:after method="after" pointcut-ref="pointcut4"/>
        </aop:aspect>
    </aop:config>

MyAspectJXML.java

package com.zmy.spring.demo3;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

/**
 *
 * @Auther: zmy
 * @create:2019-04-08-16:30
 */
public class MyAspectJXML {
    /**
    *功能描述:前置通知
    *@param:
    *@return:
    */
    public void checkPri(JoinPoint joinPoint) {
        System.out.println("===权限校验==="+joinPoint);
    }

    /**
     *功能描述:后置通知
     *@param:
     *@return:
     */
    public void writeLog(Object result) {
        System.out.println("===日志记录==="+result);
    }

    /**
     *功能描述:性能监控
     *@param:
     *@return:
     */
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("===环绕前通知===");
        Object obj = joinPoint.proceed();
        System.out.println("===环绕后通知===");
        return obj;
    }

    /**
     *功能描述:异常抛出通知
     *@param:
     *@return:
     */
    public void afterThrowing(Throwable ex) {
        System.out.println("===异常抛出通知==="+ex);
    }

    /**
     *功能描述:最终通知
     *@param:
     *@return:
     */
    public void after() {
        System.out.println("===最终通知===");
    }

}

 

1.1 SpringAOP的基于AspectJ注解开发

1.1.1 Spring的基于ApsectJ的注解的AOP开发

1.1.1.1 创建项目,引入jar

 

 

<?xml version="1.0" encoding="UTF-8"?>
<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"
    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/context
    http://www.springframework.org/schema/context/spring-context.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">

    <!--配置目标类-->
    <bean id="orderDao" class="com.zmy.spring.demo01.OrderDao"></bean>

    <!--配置切面类-->
    <bean id="myAspect" class="com.zmy.spring.demo01.MyAspectAnno"></bean>

    <!--在配置文件中开启注解AOP的开发-->
    <aop:aspectj-autoproxy/>


    
</beans>
MyAspectAnno
package com.zmy.spring.demo01;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

/**
 * @Auther: zmy
 * @create:2019-04-08-22:17
 */


@Aspect
public class MyAspectAnno {
    //前置通知
    @Before(value = "MyAspectAnno.pointcut4()")
    public void before(){
        System.out.println("前置增强=========");
    }

    //后置通知
    @AfterReturning(value = "MyAspectAnno.pointcut3()",returning = "result")
    public void afterReturning(Object result){
        System.out.println("后置增强=========="+result);
    }


    //环绕通知
    @Around(value = "MyAspectAnno.pointcut2()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前增强============");
        Object obj = joinPoint.proceed();
        System.out.println("环绕后增强============");
        return obj;
    }

    //异常抛出通知
    @AfterThrowing(value = "MyAspectAnno.pointcut1()",throwing = "throwable")
    public void afterThrowing(Throwable throwable) {
        System.out.println("异常抛出增强============"+throwable.getMessage());
    }

    //最终通知
    @After(value = "MyAspectAnno.pointcut1()")
    public void after(){
        System.out.println("最终增强============");
    }

    //切入点注解
    @Pointcut(value = "execution(* com.zmy.spring.demo01.OrderDao.find(..))")
    public void pointcut1(){}

    @Pointcut(value = "execution(* com.zmy.spring.demo01.OrderDao.update(..))")
    public void pointcut2(){}

    @Pointcut(value = "execution(* com.zmy.spring.demo01.OrderDao.delete(..))")
    public void pointcut3(){}

    @Pointcut(value = "execution(* com.zmy.spring.demo01.OrderDao.save(..))")
    public void pointcut4(){}





}
OrderDao
package com.zmy.spring.demo01;

/**
 * @Auther: zmy
 * @create:2019-04-08-21:46
 */
public class OrderDao {

    public void save(){
        System.out.println("保存订单");
    }
    public String delete(){
        System.out.println("删除订单");
        return "水晶猎龙者";
    }
    public void update(){
        System.out.println("更新订单");
    }
    public void find(){
        System.out.println("查找订单");
        //int i = 1 / 0;
    }



}
SpringTest1测试类
package com.zmy.spring.demo01;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

/**
 * Spring的AOP注解开发
 * @Auther: zmy
 * @create:2019-04-08-22:43
 */

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest1 {
    @Resource(name = "orderDao")
    private OrderDao orderDao;
    @Test
    public void demo01() {
        orderDao.delete();
        orderDao.update();
        orderDao.save();
        orderDao.find();
    }

}

SpringJDBC的模板的使用

SpringJDBC的模板

SpringEE开发的一站式的框架,有EE开发的每层的解决方案。Spring对持久层也提供了解决方案:ORM模块和JDBC的模板

Spring提供了很多的模板用于简化开发:

 

1.创建项目,引入jar

2.引入基本开发包:

3.数据库驱动

4.SpringJDBC模板的jar

 

创建数据库和表

create database spring4_day03;

use spring4_day03;

create table account(

id int primary key auto_increment,

name varchar(20),

money double

);

 

使用JDBC的模板:保存数据

将连接池和模板交给Spring管理

引入Spring的配置文件

 

  使用Jdbc的模板

 

使用开源的数据库连接池:

 DBCP的使用

1.引入jar

 

  配置DBCP连接池

 

 C3P0的使用

1. 引入c3p0连接池jar

 

配置c3p0连接池

 

抽取配置到属性文件

  定义一个属性文件

 

 Spring的配置文件中引入属性文件

 

引入属性文件的值

使用JDBC的模板完成CRUD的操作

 

package com.zmy.spring.jdbc;

import com.zmy.spring.domain.Account;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 * @Auther: zmy
 * @create:2019-04-09-11:15
 */


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JdbcDemo2 {
    @Resource(name = "jdbcTemplate")
    private JdbcTemplate jdbcTemplate;
    @Test
    public void demo1() {
        jdbcTemplate.update("delete from account where id = ?",7);

    }

    //保存用户
    @Test
    public void demo2() {
        jdbcTemplate.update("insert into account values (null , ? , ?)","百里玄策",13888d);
    }

    //删除用户
    @Test
    public void demo3() {
        jdbcTemplate.update("delete from account where id = ?",8);
    }

    //修改用户
    @Test
    public void demo4() {
        jdbcTemplate.update("update account set name = ? ,money = ? where id = ?","刘备", 13888d, 5);
    }

    //查询用户
    @Test
    public void demo5() {
        String name = jdbcTemplate.queryForObject("select name from account where id = ?", String.class, 5);
        System.out.println(name);
    }

    //统计查询
    @Test
    public void demo6() {
        Long count = jdbcTemplate.queryForObject("select count(*) from account", Long.class);
        System.out.println(count);
    }


    class MyRowMapper implements RowMapper<Account> {

        @Override
        public Account mapRow(ResultSet result, int roeNum) throws SQLException {
            Account account = new Account();
            account.setId(result.getInt("id"));
            account.setName(result.getString("name"));
            account.setMoney(result.getDouble("money"));
            return account;
        }
    }

    //封装到一个对象中
    @Test
    public void demo7() {
        Account account = jdbcTemplate.queryForObject("select * from account where id = ?", new MyRowMapper(), 5);
        System.out.println(account);
    }

    //查询多条记录
    @Test
    public void demo8() {
        List<Account> list = jdbcTemplate.query("select * from account", new MyRowMapper());
        for (Account account : list) {
            System.out.println(account);
        }
    }
}

Spring的事务管理

  事务的回顾

什么事务

  事务:逻辑上的一组操作,组成这组操作的各个单元,要么全都成功,要么全都失败。

事务的特性

  原子性:事务不可分割

  一致性:事务执行前后数据完整性保持一致

  隔离性:一个事务的执行不应该受到其他事务的干扰

  持久性:一旦事务结束,数据就持久化到数据库

如果不考虑隔离性引发安全性问题

读问题

  脏读 :一个事务读到另一个事务未提交的数据

  不可重复读 :一个事务读到另一个事务已经提交的update的数据,导致一个事务中多次查询结果不一致

  虚读、幻读 :一个事务读到另一个事务已经提交的insert的数据,导致一个事务中多次查询结果不一致。

写问题

  丢失更新

 解决读问题

设置事务的隔离级别

  Read uncommitted :未提交读,任何读问题解决不了。

  Read committed :已提交读,解决脏读,但是不可重复读和虚读有可能发生。

  Repeatable read :重复读,解决脏读和不可重复读,但是虚读有可能发生。

  Serializable :解决所有读问题。

  Spring的事务管理的API

  PlatformTransactionManager平台事务管理器

  平台事务管理器:接口,是Spring用于管理事务的真正的对象。

  DataSourceTransactionManager:底层使用JDBC管理事务

  HibernateTransactionManager :底层使用Hibernate管理事务

TransactionDefinition:事务定义信息

  事务定义:用于定义事务的相关的信息,隔离级别、超时信息、传播行为、是否只读

TransactionStatus事务的状态

事务状态:用于记录在事务管理过程中,事务的状态的对象。

事务管理的API的关系:

Spring进行事务管理的时候,首先平台事务管理器根据事务定义信息进行事务的管理,在事务管理过程中,产生各种状态,将这些状态的信息记录到事务状态的对象中。

Spring的事务的传播行为

  Spring的传播行为

   Spring中提供了七种事务的传播行为:

   保证多个操作在同一个事务中

   PROPAGATION_REQUIRED:默认值,如果A中有事务,使用A中的事务,如果A没有,创建一个新的事务,将操作包含进来

   PROPAGATION_SUPPORTS:支持事务,如果A中有事务,使用A中的事务。如果A没有事务,不使用事务。

  PROPAGATION_MANDATORY:如果A中有事务,使用A中的事务。如果A没有事务,抛出异常。

保证多个操作不在同一个事务中

   PROPAGATION_REQUIRES_NEW:如果A中有事务,将A的事务挂起(暂停),创建新事务,只包含自身操作。如果A中没有事务,创建一个新事务,包含自身操作。

  PROPAGATION_NOT_SUPPORTED:如果A中有事务,将A的事务挂起。不使用事务管理。

  PROPAGATION_NEVER:如果A中有事务,报异常。 

嵌套式事务

  PROPAGATION_NESTED:嵌套事务,如果A中有事务,按照A的事务执行,执行完成后,设置一个保存点,执行B中的操作,如果没有异常,执行通过,如果有异常,可以选择回滚到最初始位置,也可以回滚到保存点。

Spring的事务管理

搭建Spring的事务管理的环境

创建Service的接口和实现类

创建DAO的接口和实现类

 

  配置ServiceDAO:交给Spring管理

 

 DAO中编写扣钱和加钱方法:

配置连接池和JDBC的模板

DAO注入Jdbc的模板

 

 Spring的事务管理:一类:编程式事务(需要手动编写代码)--了解

第一步:配置平台事务管理器

 

 第二步:Spring提供了事务管理的模板类

配置事务的管理的模板类

 

第三步:在业务层注入事务管理的模板

 

编写事务管理的代码

 

 Spring的事务管理:二类:声明式事务管理(通过配置实现)---AOP

XML方式的声明式事务管理

第一步:引入aop的开发包

第二步:恢复转账环境

第三步:配置事务管理器

 

 第四步:配置增强

第五步:AOP的配置

 

注解方式的声明式事务管理

 第一步:引入aop的开发包

第二步:恢复转账环境

 第三步:配置事务管理器

 

第四步:开启注解事务

 

第五步:在业务层添加注解

 

 延迟加载问题的解决

 Spring提供了延迟加载的解决方案

SSH整合开发中哪些地方会出现延迟加载

  使用load方法查询某一个对象的时候(不常用)

  查询到某个对象以后,显示其关联对象。

posted @ 2019-04-07 12:43  国民老公骚颖  阅读(339)  评论(0编辑  收藏  举报