首页 技术 正文
技术 2022年11月7日
0 收藏 836 点赞 395 浏览 52834 个字

1.1 AOP概述

1.1.1什么是AOP

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

  • 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(切面):是切入点和通知(引介)的结合。

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.xsdhttp://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.xsdhttp://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.xsdhttp://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 * */@Aspectpublic 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 * */@Aspectpublic 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 * */@Aspectpublic 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 * */@Aspectpublic 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 * */@Aspectpublic 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 * */@Aspectpublic 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 * */@Aspectpublic 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.DriverjdbcUrl=jdbc:mysql:///spring3_day02user=rootpassword=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.DriverjdbcUrl=jdbc:mysql:///spring3_day02user=rootpassword=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());        }    }
下一篇: 集合set
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,088
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,564
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,412
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,185
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,822
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,905