Spring(二)
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的动态代理,对实现了接口的类生成代理。
- 动态代理(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
- 在目标类中添加一些新的方法和属性
- 前置通知org.springframework.aop.MethodBeforeAdvice
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(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
- 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开头的方法
例如:(*在正则表达式中表示任意多次,0,1或多次;.表示任意字符)
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
- 导入jar包
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns: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
- 导入jar包
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns: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()); } }
Spring(二)的更多相关文章
- spring(二、bean生命周期、用到的设计模式、常用注解)
spring(二.bean生命周期.用到的设计模式.常用注解) Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的. ...
- Spring(二)Bean入门
一.BeanFactory介绍 1.1.Bean: 在Spring技术中是基于组件的 最基本了是最常用的单元 其实实例保存在Spring的容器当中 Bean通常被定义在配置文件当中,Bean实例化由S ...
- Spring(二)——IoC
IoC(Inversion of Control)称之为控制反转,指的是在Spring框架的配置文件中声明对象,由框架负责创建对象,这叫做控制反转.实现方式有两种:DI(Dependency Inje ...
- spring(二) AOP之AspectJ框架的使用
前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以 ...
- Spring(二)之入门示例
任何编程技术,特别是入门示例,通常都是Hello World,在这里我也遵循这个业界公认的原则. 这里我使用的maven项目,大家如果想要演示,建议使用Eclipse(含maven插件)或Idea(含 ...
- Spring(二十)之使用Log4j记录日志
日志记录,也是常用的,比如异常信息记录或者其他相关信息记录,良好的日志记录有助于当系统出现某些不是特别大的问题时,可及时通过日志信息,捕捉到异常,从而确定是那段代码的问题,避免影响其他的代码. 关于m ...
- Spring(二) -- 春风拂面之 核心 AOP
”万物皆对象“是面向对象编程思想OOP(Object Oriented Programming) 的最高境界.在面向对象中,我一直将自己(开发者)放在一个至高无上的位置上,可以操纵万物(对象),犹如一 ...
- Spring(二)--IoC&AOP
IOC 一.IOC概述: 一般指控制反转(inversion of Control),把创建对象的权利交给框架,Ioc容器控制对象,是框架的重要特征,并非是面向对象编程的专用术语.它包括依赖注入(DI ...
- Spring(二)scope、集合注入、自动装配、生命周期
原文链接:http://www.orlion.ga/189/ 一.scope bean的scope属性中常用的有两种:singleton(单例,默认)和prototype(原型,每次创建新对象) 例: ...
- 学习Spring(二) 调用静态工厂方法创建Bean
1,创建抽象的产品类 package com.robert.spring.shop; public abstract class Product { } 2,创建具体产品类 package com.r ...
随机推荐
- python实现简单的循环购物车小功能
python实现简单的循环购物车小功能 # -*- coding: utf-8 -*- __author__ = 'hujianli' shopping = [ ("iphone6s&quo ...
- Vijos 1004 伊甸园日历游戏 博弈
描述 Adam和Eve玩一个游戏,他们先从1900.1.1到2001.11.4这个日期之间随意抽取一个日期出来.然后他们轮流对这个日期进行操作: 1 : 把日期的天数加1,例如1900.1.1变到19 ...
- django学习过程中知识点小结
创建项目:django-admin startproject mysite 该命令将会创建一个名为mysite的项目. mysite/ manage.py mysite/ __init__.py se ...
- Unreal Engine 4 Radiant UI 插件入门教程(二)
本篇章前提要求:在UE4上安装了Radiant UI插件.如果没有安装,请找其它教程(或者是笔者的其它的教程,目前正在写). 本教程的目的:探讨如何从网页元素中调用蓝图中的内容: 第一步: 写一个网页 ...
- 在Windows上安装Elasticsearch v5.4.2
前言 最近项目里为了加快后台系统的搜索速度,决定接入开源的搜索引擎,于是大家都在对比较常用的几个开源做技术调研,比如Lucene+盘龙分词,Solr,还有本篇要介绍的Elasticsearch.话不多 ...
- Python运维开发基础-概述-hello world
Hello World 任何一门计算机语言几乎都是从hello world开始的,为了遵从这一优秀的传统习惯,我们也从打印hello world开始. linux系统进入Python环境,直接打Pyt ...
- Python面向对象编程(三)
封装 1.为什么要封装? 封装就是要把数据属性和方法的具体实现细节隐藏起来,只提供一个接口.封装可以不用关心对象是如何构建的 2.封装包括数据的封装和函数的封装,数据的封装是为了保护隐私,函数的封装是 ...
- 开发微信小程序中SSL协议的申请、证书绑定、TLS 版本处理等
在上篇随笔<基于微信小程序的系统开发准备工作>介绍了开发微信小程序的一些前期的架构设计.技术路线 .工具准备等方面内容,本篇随笔继续这个步骤,逐步介绍我们实际开发过程中对SSL协议的申请及 ...
- InnoDB关键特性之change buffer
一.关于IOT:索引组织表 表在存储的时候按照主键排序进行存储,同时在主键上建立一棵树,这样就形成了一个索引组织表,一个表的存储方式以索引的方式来组织存储的. 所以,MySQL表一定要加上主键,通过主 ...
- poj 1200 crasy search
https://vjudge.net/problem/POJ-1200 题意: 给出一个字符串,给出子串的长度n和给出的字符串中不同字符的个数nc,统计这个字符串一共有多少不同的长度为n的子串. 思路 ...