Spring(二)

时间:2023-03-08 20:28:13
Spring(二)

1.1 AOP概述

1.1.1什么是AOP

  • AOP(Aspect Oriented Programing) 面向切面编程。
  • AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视、事务管理、安全检查、缓存)。

Spring(二)

  • Spring的AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码。
  • AspectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译的时候提供横向代码的织入。

1.1.2AOP底层原理

  • 代理机制
    • 动态代理(JDK的动态代理)
      • JDK的动态代理,对实现了接口的类生成代理。  

1.1.3Spring的AOP代理

  • JDK动态代理:对实现了接口的类生成代理
  • CGLIB代理机制:对类生成代理  

1.1.4AOP的术语

  • joinpoint(连接点):所谓的连接点是指那些被拦截到的点。在Spring中,这些点指的是方法,因为Spring只支持方法类型的连接点。
  • pointcut(切入点):所谓的切入点是指我们要对那些joinpoint进行拦截的定义。
  • Advice(通知/增强):所谓通知是指拦截到joinpoint之后所要做的事情就是通知。通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)。
  • Introduction(引介):引介是一种特殊的通知,在不修改类代码的前提下,Introduction可以在运行期为类动态的添加一些方法或属性。
  • Target(目标对象):代理的目标对象。
  • Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。Spring采用动态代理织入,而AspectJ采用编译器织入和类装载期织入。
  • Proxy(代理):一个雷被AOP织入增强后,就产生了一个结果代理类。
  • Aspect(切面):是切入点和通知(引介)的结合。

Spring(二)

1.2 AOP底层实现 

1.2.1JDK的动态代理

package cn.demo4;

public interface IUserDAO {
    public void add();
    public void update();
    public void delete();
    public void find();
}
package cn.demo4;

public class UserDAOImpl implements IUserDAO {

    @Override
    public void add() {
        System.out.println("添加用户");
    }

    @Override
    public void update() {
        System.out.println("修改用户");
    }

    @Override
    public void delete() {
        System.out.println("删除用户");
    }

    @Override
    public void find() {
        System.out.println("查询用户");
    }

}
package cn.demo4;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class UserDAOProxy implements InvocationHandler {

    private IUserDAO iUserDAO;
    public UserDAOProxy(IUserDAO iUserDAO){
        this.iUserDAO = iUserDAO;
    }

    public IUserDAO getProxy(){
        Object result = Proxy.newProxyInstance(iUserDAO.getClass().getClassLoader(), iUserDAO.getClass().getInterfaces(),this );
        return (IUserDAO) result;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if(method.getName().equals("add")){
            System.out.println("日志记录");
            Object result = method.invoke(iUserDAO, args);
            System.out.println("日志记录");
            return result;
        }
        if(method.getName().equals("delete")){
            System.out.println("日志记录");
            Object result = method.invoke(iUserDAO, args);
            System.out.println("日志记录");
            return result;
        }
        return  method.invoke(iUserDAO, args);
    }

}
package cn.demo4;

import org.junit.Test;

public class TestDemo {
    @Test
    public void demo1(){
        IUserDAO iUserDAO = new UserDAOImpl();
        IUserDAO proxy = new UserDAOProxy(iUserDAO).getProxy();
        proxy.add();
        proxy.delete();
        proxy.find();
        proxy.update();
    }
}

1.2.2CGLIB动态代理

package cn.demo5;

public class ProductDAO {

    public void add(){
        System.out.println("添加商品");
    }

    public void delete(){
        System.out.println("删除商品");
    }

    public void update(){
        System.out.println("修改商品");
    }
    public void find(){
        System.out.println("查询商品");
    }

}
package cn.demo5;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class ProductDAOProxy implements MethodInterceptor{
    private ProductDAO productDAO;
    public ProductDAOProxy(ProductDAO productDAO){
        this.productDAO = productDAO;
    }

    public ProductDAO getProxy(){
        //创建CGLIB的核心类
        Enhancer enhancer = new Enhancer();
        //为其设置父类
        enhancer.setSuperclass(productDAO.getClass());
        //设置回调
        enhancer.setCallback(this);
        //创建代理
        return (ProductDAO) enhancer.create();
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        if(method.getName().equals("add")){
            System.out.println("日志记录");
            return methodProxy.invokeSuper(proxy, args);
        }
        if(method.getName().equals("delete")){
            System.out.println("日志记录");
            return methodProxy.invokeSuper(proxy, args);
        }
        return methodProxy.invokeSuper(proxy, args);
    }
}
package cn.demo5;

import org.junit.Test;

public class TestDemo {
    @Test
    public void demo1(){
        ProductDAO proxy = new ProductDAOProxy(new ProductDAO()).getProxy();
        proxy.add();
        proxy.delete();
        proxy.find();
        proxy.update();
    }
}

 1.3 Spring中的AOP

1.3.1Spring的传统AOP

  • AOP联盟为通知Advice定义了org.aopalliance.aop.Interface.Advice。
  • Spring按照通知Advice在目标类方法的连接点位置,可以分为
    • 前置通知org.springframework.aop.MethodBeforeAdvice
      • 在目标方法执行前实施增强
    • 后置通知org.springframework.aop.AfterReturningAdvice
      • 在目标方法执行后实施增强
    • 环绕通知org.aopalliance.intercept.MethodInterceptor
      • 在目标方法执行前后实施增强
    • 异常抛出通知org.springframework.aop.ThrowsAdvice
      • 在方法抛出异常后实施增强
    • 引介通知org.springframework.aop.IntroductionInterceptor
      • 在目标类中添加一些新的方法和属性

  
1.3.2Spring中的切面类型

  • Advisor:Spring中传统切面。
    • Advisor:都是一个切点和一个通知组合。
    • Aspect:多个切点和多个通知的组合。
  • Advisor:代表一般切面。Advisor本身就是一个切面,对目标类所有哦方法进行拦截。(不带有切点的切面,针对所有方法进行拦截)
  • PointcutAdvisor:代表具有切点的切面,可以指定拦截目标类那些方法(带有切点的切面,针对某个方法进行拦截)
  • IntroductionAdvisor:代表引介切面,针对引介通知而使用切面。  

1.3.3Spring的AOP的开发--针对所有方法的增强(不带切点的切面)

  • 导入相应的jar包
    • spring-aop-3.2.0.RELEASE.jar
    • com.springsource.org.aopalliance-1.0.0.jar
  • 编写被代理的接口和实现类
package cn.demo6;

public interface ICustomerDAO {
    public void add();
    public void delete();
    public void update();
    public void find();
}
package cn.demo6;

public class CustomerDAOImpl implements ICustomerDAO {

    @Override
    public void add() {
        System.out.println("添加用户");

    }

    @Override
    public void delete() {
        System.out.println("删除用户");

    }

    @Override
    public void update() {
        System.out.println("修改用户");

    }

    @Override
    public void find() {
        System.out.println("查询用户");

    }

}
  • 编写增强的代码
package cn.demo6;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class MyBeforeAdvice implements MethodBeforeAdvice {
    /**
     * @param method 执行的方法
     * @param args 参数
     * @param target 目标对象
     */
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("前置增强");
    }

}
  • 生成代理(配置生成代理)
    • Spring基于ProxyFactoryBean类,底层自动选择使用JDK的动态代理还是CGLIB的代理。
<?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-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    <!-- 定义目标对象 -->
    <bean id="customerDAO" class="cn.demo6.CustomerDAOImpl"></bean>
    <!-- 定义增强 -->
    <bean id="beforeAdvice" class="cn.demo6.MyBeforeAdvice"></bean>

    <!-- 生成代理 -->
    <!-- Spring支持配置生成代理 -->
    <bean id="customerDAOProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 设置目标对象 -->
        <property name="target" ref="customerDAO"/>
        <!-- 设置实现接口  value接口的全路径-->
        <property name="proxyInterfaces" value="cn.demo6.ICustomerDAO" />
        <!-- 拦截的名称 -->
        <property name="interceptorNames" value="beforeAdvice"/>

    </bean>

</beans>
  • 测试
package cn.demo6;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest {
    @Autowired
    @Qualifier("customerDAOProxy")
    private ICustomerDAO customerDAO;
    @Test
    public void demo1(){
        customerDAO.add();
        customerDAO.delete();
        customerDAO.update();
        customerDAO.find();
    }

}

1.3.4Spring的AOP的开发--针对某些方法的增强(带有切点的切面)  

  • 创建被代理对象
package cn.demo7;

public class OrderDAO {
    public void add(){
        System.out.println("增加");
    }
    public void delete(){
        System.out.println("删除");
    }
    public void find(){
        System.out.println("查询");
    }
    public void update(){
        System.out.println("修改");
    }
}
  • 编写要增强的类
package cn.demo7;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyAroundAdvice implements MethodInterceptor{

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("方法执行前--日志记录");
        Object result = invocation.proceed();
        System.out.println("方法执行后--日志记录");
        return result;
    }

}
  • 生成代理
    <!-- 定义切点切面 -->
    <bean id="pointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <!-- 定义表达式来规定哪些方法执行拦截 -->
        <property name="pattern" value="cn.demo7.OrderDAO.add.*"/>
        <!-- 应用增强 -->
        <property name="advice" ref="aroundAdvice"/>
    </bean>

    <!-- 定义目标对象 -->
    <bean id="orderDAO" class="cn.demo7.OrderDAO"></bean>
    <!-- 定义增强 -->
    <bean id="aroundAdvice" class="cn.demo7.MyAroundAdvice"/>
    <!-- 定义生成的代理对象 -->
    <bean id="orderDAOProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 配置目标 -->
        <property name="target" ref="orderDAO"></property>
        <!-- 针对类的代理 -->
        <property name="proxyTargetClass" value="true"/>
        <!-- 在目标上应用增强 -->
        <property name="interceptorNames" value="pointcutAdvisor"/>
    </bean>
    
  • 测试类
package cn.demo7;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest {
    @Autowired
    @Qualifier("orderDAOProxy")
    private OrderDAO orderDAO;
    @Test
    public void demo1(){
        orderDAO.add();
        orderDAO.delete();
        orderDAO.find();
        orderDAO.update();
    }

}

1.3.5自动代理

  • 前面的案例中,每个代理都是通过ProxyFactoryBean织入切面代理,在实际开发中,非常多的Bean每个都配置ProxyFactoryBean开发维护量巨大。
  • 自动创建代理:-----基于后处理Bean,在Bean创建的过程中完成的增强。生成的Bean就是代理。
    • BeanNameAutoProxyCreator根据Bean名称创建
package cn.demo6;

public interface ICustomerDAO {
    public void add();
    public void delete();
    public void update();
    public void find();
}
package cn.demo6;

public class CustomerDAOImpl implements ICustomerDAO {

    @Override
    public void add() {
        System.out.println("添加用户");

    }

    @Override
    public void delete() {
        System.out.println("删除用户");

    }

    @Override
    public void update() {
        System.out.println("修改用户");

    }

    @Override
    public void find() {
        System.out.println("查询用户");

    }

}
package cn.demo6;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class MyBeforeAdvice implements MethodBeforeAdvice {
    /**
     * @param method 执行的方法
     * @param args 参数
     * @param target 目标对象
     */
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("前置增强");
    }

}
package cn.demo7;

public class OrderDAO {
    public void add(){
        System.out.println("增加");
    }
    public void delete(){
        System.out.println("删除");
    }
    public void find(){
        System.out.println("查询");
    }
    public void update(){
        System.out.println("修改");
    }
}
package cn.demo7;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyAroundAdvice implements MethodInterceptor{

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("方法执行前--日志记录");
        Object result = invocation.proceed();
        System.out.println("方法执行后--日志记录");
        return result;
    }

}
<?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-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    <!-- 定义目标对象 -->
    <bean id="customerDAO" class="cn.demo6.CustomerDAOImpl"></bean>
    <!-- 定义增强 -->
    <bean id="beforeAdvice" class="cn.demo6.MyBeforeAdvice"></bean>

    <!-- 定义目标对象 -->
    <bean id="orderDAO" class="cn.demo7.OrderDAO"></bean>
    <!-- 定义增强 -->
    <bean id="aroundAdvice" class="cn.demo7.MyAroundAdvice"/>

    <!-- 自动代理:按名称的代理 基于后处理Bean,后处理Bea不需要配置id -->
    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" >
        <property name="beanNames" value="*DAO"/>
        <property name="interceptorNames" value="beforeAdvice"/>
    </bean>

</beans>
package cn.demo8;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import cn.demo6.ICustomerDAO;
import cn.demo7.OrderDAO;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class SpringTest {
    @Autowired
    @Qualifier("customerDAO")
    private ICustomerDAO customerDAO;
    @Autowired
    @Qualifier("orderDAO")
    private OrderDAO orderDAO;

    @Test
    public void demo1(){
        orderDAO.add();
        orderDAO.delete();

        customerDAO.add();
        customerDAO.delete();

    }

}
    • DefaultAdvisorAutoProxyCreator根据Advisor本身包含信息创建代理
package cn.demo6;

public interface ICustomerDAO {
    public void add();
    public void delete();
    public void update();
    public void find();
}
package cn.demo6;

public class CustomerDAOImpl implements ICustomerDAO {

    @Override
    public void add() {
        System.out.println("添加用户");

    }

    @Override
    public void delete() {
        System.out.println("删除用户");

    }

    @Override
    public void update() {
        System.out.println("修改用户");

    }

    @Override
    public void find() {
        System.out.println("查询用户");

    }

}
package cn.demo6;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class MyBeforeAdvice implements MethodBeforeAdvice {
    /**
     * @param method 执行的方法
     * @param args 参数
     * @param target 目标对象
     */
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("前置增强");
    }

}
package cn.demo7;

public class OrderDAO {
    public void add(){
        System.out.println("增加");
    }
    public void delete(){
        System.out.println("删除");
    }
    public void find(){
        System.out.println("查询");
    }
    public void update(){
        System.out.println("修改");
    }
}
package cn.demo7;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyAroundAdvice implements MethodInterceptor{

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("方法执行前--日志记录");
        Object result = invocation.proceed();
        System.out.println("方法执行后--日志记录");
        return result;
    }

}
<?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-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    <!-- 定义目标对象 -->
    <bean id="customerDAO" class="cn.demo6.CustomerDAOImpl"></bean>
    <!-- 定义增强 -->
    <bean id="beforeAdvice" class="cn.demo6.MyBeforeAdvice"></bean>

    <!-- 定义目标对象 -->
    <bean id="orderDAO" class="cn.demo7.OrderDAO"></bean>
    <!-- 定义增强 -->
    <bean id="aroundAdvice" class="cn.demo7.MyAroundAdvice"/>

    <!-- 定义一个带有切点的切面 -->
    <bean id="pointcut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="pattern" value=".*add.*"/>
        <property name="advice" ref="aroundAdvice"/>
    </bean>

    <!-- 自动生成代理 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">

    </bean>

</beans>
package cn.demo9;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import cn.demo6.ICustomerDAO;
import cn.demo7.OrderDAO;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext3.xml")
public class SpringTest {
    @Autowired
    @Qualifier("customerDAO")
    private ICustomerDAO customerDAO;
    @Autowired
    @Qualifier("orderDAO")
    private OrderDAO orderDAO;

    @Test
    public void demo1(){
        orderDAO.add();
        orderDAO.delete();

        customerDAO.add();
        customerDAO.delete();

    }

}
    • AnnotationAwareAspectAutoProxyCreator基于Bean中的AspectJ注解进行自动代理。

区分基于ProxyFactoryBean的代理与自动代理的区别?

  • ProxyFactoryBean是先有被代理的对象,将被代理的对象传入代理类中生成代理。
  • 自动代理是基于后处理Bean,在Bean生成过程中产生了代理对象,把代理对象返回,生成的Bean已经是代理对象了。

  

1.4 Spring的AspectJ的AOP  

1.4.1AspectJ简介

  • AspectJ是一个基于Java语言的AOP框架。
  • Spring2.0以后新增了对AspectJ切点表达式支持。
  • @AspectJ是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面。
  • 新版本的Spring框架,建议使用AspectJ方式来开发AOP。

      

1.4.2AspectJ表达式

  • 语法:execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
  • 例如:(*在正则表达式中表示任意多次,0,1或多次;.表示任意字符)

    • execution(public * *(..)) 匹配所有类public方法
    • execution(* cn.spring3.demo1.dao.*(..)) 匹配cn.spring3.demo1.dao包下的所有方法
    • execution(*  cn.spring3.demo1.dao..*(..)) 匹配cn.spring3.demo1.dao包及子包的所有方法
    • execution(* cn.spring3.demo1.dao.GenericDAO+.*(..))  匹配GenericDAO
    • execution(* save(..)) 匹配所有save开头的方法

1.4.3AspectJ提供不同的通知类型

  • @Before 前置通知
  • @AfterReturning 后置通知
  • @Around 环绕通知
  • @AfterThrowing 抛出通知
  • @After 最终通知,不管是否异常,该通知都会执行
  • @DeclareParents引介通知

1.4.4基于注解

  • 引入相应的jar包
    • spring-aop-3.2.0.RELEASE.jar
    • com.springsource.org.aopalliance-1.0.0.jar
    • spring-aspects-3.2.0.RELEASE.jar
    • com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
  • 编写被增强类(目标类)
package cn.demo1;

public class UserDAO {
    public void add(){
        System.out.println("添加用户");
    }
    public void update(){
        System.out.println("修改用户");
    }
    public void delete(){
        System.out.println("删除用户");
    }
    public void find(){
        System.out.println("查询用户");
    }
}
  • 使用AspectJ注解形式
package cn.demo1;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * 切面类:就是切点与增强的结合
 * @author love
 *
 */
@Aspect
public class MyAspect {

    @Before("execution(* cn.demo1.UserDAO.*(..))")
    public void before(){
        System.out.println("前置增强。。。。");
    }

}
  • 创建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"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    <!-- 开启自动生成代理 -->
    <aop:aspectj-autoproxy/>

    <bean id="userDAO" class="cn.demo1.UserDAO"/>

    <bean id="myAspect" class="cn.demo1.MyAspect"/>

</beans>
  • 测试类
package cn.demo1;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest {
    @Autowired
    @Qualifier("userDAO")
    private UserDAO userDAO;

    @Test
    public void demo1(){
        userDAO.add();
        userDAO.delete();
        userDAO.find();
        userDAO.update();
    }

}

1.4.4AspectJ通知类型

  • @Before 前置通知,在方法之前执行,没有办法阻止目标方法执行。
package cn.demo1;

public class UserDAO {
    public void add(){
        System.out.println("添加用户");
    }
    public void update(){
        System.out.println("修改用户");
    }
    public void delete(){
        System.out.println("删除用户");
    }
    public void find(){
        System.out.println("查询用户");
    }
}
package cn.demo1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * 切面类:就是切点与增强的结合
 * @author love
 *
 */
@Aspect
public class MyAspect {

    @Before("execution(* cn.demo1.UserDAO.add(..))")
    public void before(JoinPoint joinPoint){
        System.out.println("前置增强。。。。"+joinPoint);
    }

}
<?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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    <!-- 开启自动生成代理 -->
    <aop:aspectj-autoproxy/>

    <bean id="userDAO" class="cn.demo1.UserDAO"/>

    <bean id="myAspect" class="cn.demo1.MyAspect"/>

</beans>
package cn.demo1;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest {
    @Autowired
    @Qualifier("userDAO")
    private UserDAO userDAO;

    @Test
    public void demo1(){
        userDAO.add();
        userDAO.delete();
        userDAO.find();
        userDAO.update();
    }

}
  • @AfterReturning 后置通知,获取方法的返回值。 
package cn.demo1;

public class UserDAO {
    public void add(){
        System.out.println("添加用户");
    }
    public void update(){
        System.out.println("修改用户");
    }
    public void delete(){
        System.out.println("删除用户");
    }
    public int find(){
        System.out.println("查询用户");
        return 1;
    }
}
package cn.demo1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * 切面类:就是切点与增强的结合
 * @author love
 *
 */
@Aspect
public class MyAspect {

    @Before("execution(* cn.demo1.UserDAO.add(..))")
    public void before(JoinPoint joinPoint){
        System.out.println("前置增强。。。。"+joinPoint);
    }
    @AfterReturning(value="execution(* cn.demo1.UserDAO.find(..))",returning="returnVal")
    public void afterReturning(Object returnVal){
        System.out.println("后置增强。。。。"+returnVal);
    }
}
<?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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    <!-- 开启自动生成代理 -->
    <aop:aspectj-autoproxy/>

    <bean id="userDAO" class="cn.demo1.UserDAO"/>

    <bean id="myAspect" class="cn.demo1.MyAspect"/>

</beans>
package cn.demo1;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest {
    @Autowired
    @Qualifier("userDAO")
    private UserDAO userDAO;

    @Test
    public void demo1(){
        userDAO.add();
        userDAO.delete();
        userDAO.find();
        userDAO.update();
    }

}
  • @Around 环绕通知,可以在方法之前和方法之后执行的,可以阻止目标方法的执行。
package cn.demo1;

public class UserDAO {
    public void add(){
        System.out.println("添加用户");
    }
    public void update(){
        System.out.println("修改用户");
    }
    public void delete(){
        System.out.println("删除用户");
    }
    public int find(){
        System.out.println("查询用户");
        return 1;
    }
}
package cn.demo1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * 切面类:就是切点与增强的结合
 * @author love
 *
 */
@Aspect
public class MyAspect {

    @Before("execution(* cn.demo1.UserDAO.add(..))")
    public void before(JoinPoint joinPoint){
        System.out.println("前置增强。。。。"+joinPoint);
    }

    @AfterReturning(value="execution(* cn.demo1.UserDAO.find(..))",returning="returnVal")
    public void afterReturning(Object returnVal){
        System.out.println("后置增强。。。。"+returnVal);
    }
    @Around(value="execution(* cn.demo1.UserDAO.update(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("环绕前增强");
        Object obj = joinPoint.proceed();
        System.out.println("环绕后增强");
        return obj;
    }
}
<?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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    <!-- 开启自动生成代理 -->
    <aop:aspectj-autoproxy/>

    <bean id="userDAO" class="cn.demo1.UserDAO"/>

    <bean id="myAspect" class="cn.demo1.MyAspect"/>

</beans>
package cn.demo1;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest {
    @Autowired
    @Qualifier("userDAO")
    private UserDAO userDAO;

    @Test
    public void demo1(){
        userDAO.add();
        userDAO.delete();
        userDAO.find();
        userDAO.update();
    }

}
  • AfterThrowing抛出异常通知
package cn.demo1;

public class UserDAO {
    public void add(){
        System.out.println("添加用户");
    }
    public void update(){
        System.out.println("修改用户");
    }
    public void delete(){
        System.out.println("删除用户");
    }
    public int find(){
        System.out.println("查询用户");
        int i = 1/0;
        return 1;
    }
}
package cn.demo1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * 切面类:就是切点与增强的结合
 * @author love
 *
 */
@Aspect
public class MyAspect {

    @Before("execution(* cn.demo1.UserDAO.add(..))")
    public void before(JoinPoint joinPoint){
        System.out.println("前置增强。。。。"+joinPoint);
    }

    @AfterReturning(value="execution(* cn.demo1.UserDAO.find(..))",returning="returnVal")
    public void afterReturning(Object returnVal){
        System.out.println("后置增强。。。。"+returnVal);
    }
    @Around(value="execution(* cn.demo1.UserDAO.update(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("环绕前增强");
        Object obj = joinPoint.proceed();
        System.out.println("环绕后增强");
        return obj;
    }
    @AfterThrowing(value="execution(* cn.demo1.UserDAO.find(..))",throwing="e")
    public void afterThrowing(Throwable e){
        System.out.println("出异常了。。。"+e.getMessage());
    }

}
<?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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    <!-- 开启自动生成代理 -->
    <aop:aspectj-autoproxy/>

    <bean id="userDAO" class="cn.demo1.UserDAO"/>

    <bean id="myAspect" class="cn.demo1.MyAspect"/>

</beans>
package cn.demo1;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest {
    @Autowired
    @Qualifier("userDAO")
    private UserDAO userDAO;

    @Test
    public void demo1(){
        userDAO.add();
        userDAO.delete();
        userDAO.find();
        userDAO.update();
    }

}
  • After 最终通知
package cn.demo1;

public class UserDAO {
    public void add(){
        System.out.println("添加用户");
    }
    public void update(){
        System.out.println("修改用户");
    }
    public void delete(){
        System.out.println("删除用户");
    }
    public int find(){
        System.out.println("查询用户");
        int i = 1/0;
        return 1;
    }
}
package cn.demo1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * 切面类:就是切点与增强的结合
 * @author love
 *
 */
@Aspect
public class MyAspect {

    @Before("execution(* cn.demo1.UserDAO.add(..))")
    public void before(JoinPoint joinPoint){
        System.out.println("前置增强。。。。"+joinPoint);
    }

    @AfterReturning(value="execution(* cn.demo1.UserDAO.find(..))",returning="returnVal")
    public void afterReturning(Object returnVal){
        System.out.println("后置增强。。。。"+returnVal);
    }
    @Around(value="execution(* cn.demo1.UserDAO.update(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("环绕前增强");
        Object obj = joinPoint.proceed();
        System.out.println("环绕后增强");
        return obj;
    }
    @AfterThrowing(value="execution(* cn.demo1.UserDAO.find(..))",throwing="e")
    public void afterThrowing(Throwable e){
        System.out.println("出异常了。。。"+e.getMessage());
    }
    @After(value="execution(* cn.demo1.UserDAO.find(..))")
    public void after(){
        System.out.println("最终通知");
    }

}
<?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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    <!-- 开启自动生成代理 -->
    <aop:aspectj-autoproxy/>

    <bean id="userDAO" class="cn.demo1.UserDAO"/>

    <bean id="myAspect" class="cn.demo1.MyAspect"/>

</beans>
package cn.demo1;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest {
    @Autowired
    @Qualifier("userDAO")
    private UserDAO userDAO;

    @Test
    public void demo1(){
        userDAO.add();
        userDAO.delete();
        userDAO.find();
        userDAO.update();
    }

}

1.4.5切点的注解

  • 在每个通知内定义切点,会造成工作量大,不易维护,对于重复的切点,可以使用@Pointcut进行定义。
  • 切点方法:private void 无参方法,方法名为切点名。
  • 当多个切点时,可以使用||进行连接。
package cn.demo1;

public class UserDAO {
    public void add(){
        System.out.println("添加用户");
    }
    public void update(){
        System.out.println("修改用户");
    }
    public void delete(){
        System.out.println("删除用户");
    }
    public int find(){
        System.out.println("查询用户");
        int i = 1/0;
        return 1;
    }
}
package cn.demo1;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/**
 * 切面类:就是切点与增强的结合
 * @author love
 *
 */
@Aspect
public class MyAspect {

    @Before("execution(* cn.demo1.UserDAO.add(..))")
    public void before(JoinPoint joinPoint){
        System.out.println("前置增强。。。。"+joinPoint);
    }

    @AfterReturning(value="MyAspect.pointcut()",returning="returnVal")
    public void afterReturning(Object returnVal){
        System.out.println("后置增强。。。。"+returnVal);
    }
    @Around(value="execution(* cn.demo1.UserDAO.update(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("环绕前增强");
        Object obj = joinPoint.proceed();
        System.out.println("环绕后增强");
        return obj;
    }
    @AfterThrowing(value="MyAspect.pointcut()",throwing="e")
    public void afterThrowing(Throwable e){
        System.out.println("出异常了。。。"+e.getMessage());
    }
    @After("MyAspect.pointcut()")
    public void after(){
        System.out.println("最终通知");
    }

    @Pointcut("execution(* cn.demo1.UserDAO.find(..))")
    private void pointcut(){}

}
<?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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    <!-- 开启自动生成代理 -->
    <aop:aspectj-autoproxy/>

    <bean id="userDAO" class="cn.demo1.UserDAO"/>

    <bean id="myAspect" class="cn.demo1.MyAspect"/>

</beans>
package cn.demo1;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest {
    @Autowired
    @Qualifier("userDAO")
    private UserDAO userDAO;

    @Test
    public void demo1(){
        userDAO.add();
        userDAO.delete();
        userDAO.find();
        userDAO.update();
    }

}
  • Advisor和Aspect的区别?
    • Advisor:Spring传统意义上的切面,支持一个切点和一个通知的组合。
    • Aspect:支持多个切点和多个通知的组合。

1.4.6基于XML  

  • 定义被增强的类--目标类
package cn.demo2;

public class ProductDAO {
    public void add(){
        System.out.println("添加商品");
    }
    public void update(){
        System.out.println("修改商品");
    }
    public void delete(){
        System.out.println("删除商品");
    }
    public void find(){
        System.out.println("查询商品");
    }
}
  • 定义切面
package cn.demo2;
/**
 * 切面类
 */
public class MyAspect {

    public void before(){
        System.out.println("前置通知");
    }

}
  • applicationContext2.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"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    <!-- 定义被增强的类 -->
    <bean id="productDAO" class="cn.demo2.ProductDAO"/>
    <!-- 定义切面 -->
    <bean id="myAspect" class="cn.demo2.MyAspect"/>

    <!-- 定义AOP的配置 -->
    <aop:config>
        <!-- 定义切点 -->
        <aop:pointcut expression="execution(* cn.demo2.ProductDAO.add(..))" id="pointcut"/>
        <aop:aspect ref="myAspect">
            <aop:before method="before" pointcut-ref="pointcut" />
        </aop:aspect>
    </aop:config>

</beans>
  • 测试类
package cn.demo2;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class SpringTest {
    @Autowired
    @Qualifier("productDAO")
    private ProductDAO productDAO;

    @Test
    public void demo1(){
        productDAO.add();
        productDAO.delete();
        productDAO.find();
        productDAO.update();
    }

}

1.5 Spring的JDBC Template

1.5.1JDBC Template

  • Spring JDBC是Spring提供的持久层技术。
  • 简化JDBC API开发,使用上和Apache公司的DButils框架类似。

1.5.2Spring对不同持久层技术的支持

  • Spring为各种支持的持久化技术,都提供了简单模板和回调
ORM持久层技术 模板类
JDBC

org.springframework.jdbc.core.JdbcTemplate

Hibernate3.0

org.springframework.orm.hibernate3.HibernateTemplate

IBatis(MyBatis)

org.springframework.orm.ibatis.SqlMapClientTemplate

JPA

org.springframework.orm.jpa.JpaTemplate

1.5.3 开发JDBC Template入门

  • 引入jar包
    • 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
    • com.springsource.org.apache.commons.logging-1.1.1.jar
    • com.springsource.org.apache.log4j-1.2.15.jar
    • spring-jdbc-3.2.0.RELEASE.jar
    • spring-tx-3.2.0.RELEASE.jar
    • 数据库驱动
  • 创建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"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

</beans>
  • 测试
package cn.demo1;

import org.junit.Test;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

public class SpringTest {
    @Test
    public void demo1(){
        //创建连接池
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        //设置参数
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///spring3_day02");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        //使用JDBC模板
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        jdbcTemplate.execute("create table user( id int primary key auto_increment,name varchar(20))");

    }
}

1.5.4配置连接池

  • 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:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

    <!-- 配置Spring默认的连接池 -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///spring3_day02"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

    <!-- 定义JDBC Template -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>
    • 测试类
package cn.demo1;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

public class SpringTest {

    @Test
    public void demo2(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        JdbcTemplate jdbcTemplate = (JdbcTemplate) applicationContext.getBean("jdbcTemplate");
        jdbcTemplate.execute("insert into user (name) values ('哈哈')");

    }
}
  • DBCP连接池
    • 导入jar包
      • com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar
      • com.springsource.org.apache.commons.pool-1.5.3.jar
    • 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"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

    <!-- 配置Spring默认的连接池 -->
    <!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///spring3_day02"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean> -->

    <!-- 配置DBCP连接池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///spring3_day02"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

    <!-- 定义JDBC Template -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>
    • 测试类
package cn.demo1;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

public class SpringTest {

    @Test
    public void demo2(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        JdbcTemplate jdbcTemplate = (JdbcTemplate) applicationContext.getBean("jdbcTemplate");
        jdbcTemplate.execute("insert into user (name) values ('呵呵')");

    }
}
  • C3p0连接池
    • 导入jar包
      • com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
    • 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"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

    <!-- 配置Spring默认的连接池 -->
    <!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///spring3_day02"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean> -->

    <!-- 配置DBCP连接池 -->
    <!-- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///spring3_day02"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean> -->

    <!-- 配置C3p0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql:///spring3_day02"/>
        <property name="user" value="root"/>
        <property name="password" value="root"/>
    </bean>

    <!-- 定义JDBC Template -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>
    • 测试类
package cn.demo1;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

public class SpringTest {

    @Test
    public void demo2(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        JdbcTemplate jdbcTemplate = (JdbcTemplate) applicationContext.getBean("jdbcTemplate");
        jdbcTemplate.execute("insert into user (name) values ('嘻嘻')");

    }
}

1.5.5设置参数到属性文件

  • 在src下新建了一个jdbc.properties
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql:///spring3_day02
user=root
password=root
  • 需要在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"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

    <!-- 配置Spring默认的连接池 -->
    <!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///spring3_day02"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean> -->

    <!-- 配置DBCP连接池 -->
    <!-- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///spring3_day02"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean> -->

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:jdbc.properties"></property>
    </bean>

    <!-- 配置C3p0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${driverClass}"/>
        <property name="jdbcUrl" value="${jdbcUrl}"/>
        <property name="user" value="${user}"/>
        <property name="password" value="${password}"/>
    </bean>

    <!-- 定义JDBC Template -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</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:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

    <!-- 配置Spring默认的连接池 -->
    <!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///spring3_day02"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean> -->

    <!-- 配置DBCP连接池 -->
    <!-- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///spring3_day02"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean> -->

    <!-- <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:jdbc.properties"></property>
    </bean> -->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!-- 配置C3p0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${driverClass}"/>
        <property name="jdbcUrl" value="${jdbcUrl}"/>
        <property name="user" value="${user}"/>
        <property name="password" value="${password}"/>
    </bean>

    <!-- 定义JDBC Template -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>
  • 测试
package cn.demo1;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

public class SpringTest {

    @Test
    public void demo2(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        JdbcTemplate jdbcTemplate = (JdbcTemplate) applicationContext.getBean("jdbcTemplate");
        jdbcTemplate.execute("insert into user (name) values ('笨笨')");

    }
}

1.5.6JDBC Template的CRUD操作

  • 为了方便DAO中注入JdbcTemplate,Spring为每一个持久化技术都提供了支持类。
ORM持久化技术 支持类
JDBC

org.springframework.jdbc.core.support.JdbcDaoSupport

 Hibernate3.0

org.springframework.orm.hibernate3.support.HibernateDaoSupport

 iBatis

org.springframework.orm.ibatis.support.SqlMapClientDaoSupport

  

  

    

      

1.5.7JDBC Template的增、删、改操作

  • 实体类User
package cn.demo1;

public class User {
    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

}
  • UserDAO
package cn.demo1;

import org.springframework.jdbc.core.support.JdbcDaoSupport;

public class UserDAO extends JdbcDaoSupport{

    public void add(User user){
        String sql = "insert into user values(null,?)";
        this.getJdbcTemplate().update(sql, user.getName());
    }

    public void update(User user){
        String sql = "update user set name = ? where id = ?";
        this.getJdbcTemplate().update(sql, user.getName(),user.getId());
    }

    public void delete(User user){
        String sql = "delete from user where id = ?";
        this.getJdbcTemplate().update(sql, user.getId());
    }

}
  • jdbc.properties
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql:///spring3_day02
user=root
password=root
  • 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"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

    <!-- 配置Spring默认的连接池 -->
    <!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///spring3_day02"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean> -->

    <!-- 配置DBCP连接池 -->
    <!-- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///spring3_day02"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean> -->

    <!-- <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:jdbc.properties"></property>
    </bean> -->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!-- 配置C3p0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${driverClass}"/>
        <property name="jdbcUrl" value="${jdbcUrl}"/>
        <property name="user" value="${user}"/>
        <property name="password" value="${password}"/>
    </bean>

    <!-- 定义JDBC Template -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="userDAO" class="cn.demo1.UserDAO">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>

</beans>
  • 测试类
package cn.demo1;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest {
    @Autowired
    @Qualifier("userDAO")
    private UserDAO userDAO;

    @Test
    public void demo1(){
        User user = new User();
        user.setName("哈哈");
        userDAO.add(user);
    }
    @Test
    public void demo2(){
        User user = new User();
        user.setId(1);
        user.setName("呵呵");
        userDAO.update(user);
    }
    @Test
    public void demo3(){
        User user = new User();
        user.setId(1);
        userDAO.delete(user);
    }

}

1.5.8JDBC Template的查询操作

  • 简单查询
    • select count(*) from user;
    • select name from user where id = ?;
public int findCount(){
        String sql = "select count(*) from user";
        return this.getJdbcTemplate().queryForInt(sql);

 }
  @Test
    public void demo4(){
        System.out.println("总共:"+userDAO.findCount());
    }
public String findNameById(int id){
        String sql = "select name from user where id = ?";
        return this.getJdbcTemplate().queryForObject(sql,String.class,id);
    }
@Test
    public void demo5(){
        System.out.println(userDAO.findNameById(1));
    }
  • 复杂查询:返回对象和对象集合
    • select * from user where id = ?;
    • select * from user;      
public User findById(int id){
        String sql = "select * from user where id = ?";
        return (User) this.getJdbcTemplate().query(sql,new ResultSetExtractor<User>(){

            @Override
            public User extractData(ResultSet rs) throws SQLException, DataAccessException {
                User user = new User();
                if(rs.next()){
                    user.setId(rs.getInt(1));
                    user.setName(rs.getString(2));
                }

                return user;
            }

        }, id);
    }
@Test
    public void demo6(){
        User user = userDAO.findById(2);
        System.out.println(user.getId()+","+user.getName());
    }
    public List<User> findAll(){
        String sql = "select * from user";
        return this.getJdbcTemplate().query(sql, new RowMapper<User>(){

            @Override
            public User mapRow(ResultSet rs, int paramInt) throws SQLException {
                User user = new User();
                user.setId(rs.getInt(1));
                user.setName(rs.getString(2));
                return user;
            }});
    }
@Test
    public void demo7(){
        List<User> users = userDAO.findAll();
        for (User user : users) {
            System.out.println(user.getId()+","+user.getName());
        }
    }