什么是AOP?
AOP底层原理:AOP就是代理机制,动态代理:(JDK 中使用) JDK动态代理,对实现了接口的类生成代理。
package spring3.aop.demo1; /** * DAO的接口 * */ public interface UserDao { public void add(); public void update(); }UserDaoImpl
package spring3.aop.demo1; public class UserDaoImpl implements UserDao { @Override public void add() { System.out.println("添加用户"); } @Override public void update() { System.out.println("修改用户"); } }JDKProxy
package spring3.aop.demo1; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * JDK的动态代理机制 * * @author liuxun * */ public class JDKProxy implements InvocationHandler { private UserDao userDao; public JDKProxy(UserDao userDao) { super(); this.userDao = userDao; } public UserDao createProxy() { UserDao proxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), this); return proxy; } @Override // 调用目标对象的任何一个方法都相当于invoke() public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("add".equals(method.getName())) { // 记录日志 System.out.println("日志记录==================="); Object result = method.invoke(userDao, args); return result; } return method.invoke(userDao, args); } }SpringTest1
package spring3.aop.demo1; import org.junit.Test; public class SpringTest1 { @Test public void demo1() { UserDao userDao = new UserDaoImpl(); userDao.add(); userDao.update(); } @Test public void demo2() { // 被代理对象 UserDao userDao = new UserDaoImpl(); // 创建代理对象的时候传入被代理对象 UserDao proxy = new JDKProxy(userDao).createProxy(); proxy.add(); proxy.update(); } }运行结果如下:
package spring3.aop.demo2; public class ProductDao { public void add() { System.out.println("添加商品..."); } public void update() { System.out.println("修改商品..."); } }CGLibProxy
package spring3.aop.demo2; import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; /** * 使用CGLib生成代理对象 * */ public class CGLibProxy implements MethodInterceptor { private ProductDao productDao; public CGLibProxy(ProductDao productDao) { super(); this.productDao = productDao; } public ProductDao createProxy() { // 使用CGLIB生成代理 // 1.创建核心类 Enhancer enhancer = new Enhancer(); // 2.为其设置父类 enhancer.setSuperclass(productDao.getClass()); // 3.设置回调 enhancer.setCallback(this); // 4.创建代理 return (ProductDao) enhancer.create(); } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { if ("add".equals(method.getName())) { System.out.println("日志记录================="); // Object obj=method.invoke(productDao, args); Object obj = methodProxy.invokeSuper(proxy, args);// 代理方法中执行代理对象父类中的方法 return obj; } return methodProxy.invokeSuper(proxy, args); } }SpringTest2
package spring3.aop.demo2; import org.junit.Test; public class SpringTest2 { @Test public void demo1() { ProductDao productDao = new ProductDao(); productDao.add(); productDao.update(); } @Test public void demo2() { ProductDao productDao = new ProductDao(); ProductDao proxy=new CGLibProxy(productDao).createProxy(); proxy.add(); proxy.update(); } }运行结果如下所示
/**
*@param obj CGlib根据指定父类生成的代理对象
*@param method 拦截的方法
*@param args 拦截方法的参数数组
*@param proxy 方法的代理对象,用于执行父类的方法
*@return
*/
public Object intercept(Object obj, Methodmethod, Object[] args,
MethodProxyproxy) throws Throwable {
... ...
}
<bean id="helloAdvice" class="cn.test.springaop.HelloServiceBeforeAdvice"></bean> <bean id="target" class="cn.test.springaop.HelloService" /> <bean id="helloService" class="org.springframework.aop.framework.ProxyFactoryBean" > <property name="proxyInterfaces" value="cn.test.springaop.IHelloService" /> <!--如果不是针对接口代理,可以设置 <property name="proxyTargetClass" value="true"></property> ,将使用CGLib--> <property name="interceptorNames" value="helloAdvice"></property> <property name="target" ref="target"></property> </bean>spring生成代理基于ProxyFactoryBean类,底层自动选择使用JDK的动态代理还是CGLIB的代理。
package spring3.aop.demo3; public interface CustomerDao { public void add(); public void update(); public void delete(); public void find(); }真实实现类CustomerDaoImpl
package spring3.aop.demo3; public class CustomerDaoImpl implements CustomerDao { public void add() { System.out.println("添加客户"); } public void update() { System.out.println("修改客户"); } public void delete() { System.out.println("删除客户"); } public void find() { System.out.println("查询客户"); } }定义增强类型MyBeforeAdvice
package spring3.aop.demo3; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; /** * 前置增强 */ public class MyBeforeAdvice implements MethodBeforeAdvice { /** * method:执行的方法 * args:参数 * target:目标对象 */ public void before(Method method, Object[] args, Object target) throws Throwable { 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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 不带有切点的切面 --> <!-- 定义目标对象 --> <bean id="customerDao" class="spring3.aop.demo3.CustomerDaoImpl" /> <!-- 定义增强 --> <bean id="beforeAdvice" class="spring3.aop.demo3.MyBeforeAdvice" /> <!-- spring支持配置生成代理 --> <bean id="customerDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 设置目标对象 --> <property name="target" ref="customerDao" /> <!-- 设置实现的接口,value中写接口的全路径 --> <property name="proxyInterfaces" value="spring3.aop.demo3.CustomerDao" /> <!-- 需要使用value: 需要实现增强代码类的名称 --> <property name="interceptorNames" value="beforeAdvice" /> <!-- 强制使用CGLIB代理 --> <property name="optimize" value="true" /> </bean> </beans>新建测试类SpringTest3
package spring3.aop.demo3; 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 SpringTest3 { @Autowired // @Qualifier("customerDao") // 需要注入真实的对象,必须注入代理对象 @Qualifier("customerDaoProxy") private CustomerDao customerDao; @Test public void demo1() { customerDao.add(); customerDao.update(); customerDao.delete(); customerDao.find(); } }测试demo1 运行结果如下
package spring3.aop.demo4; /** * 目标对象 * */ public class OrderDao { public void add() { System.out.println("添加订单"); } public void update() { System.out.println("修改订单"); } public void delete() { System.out.println("删除订单"); } public void find() { System.out.println("查询订单"); } }MyAroundAdvice (Advice通知增强类)
package spring3.aop.demo4; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; /** * 增强的类 * 使用的是环绕增强 * 注意:对于增强类型的接口可以使用AOP联盟的也可以使用Spring扩展后自带的 */ public class MyAroundAdvice implements MethodInterceptor { @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { System.out.println("环绕前增强..."); Object result=methodInvocation.proceed(); // 指定目标对象的方法 System.out.println("环绕后增强..."); return result; } }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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 带有切点的切面 --> <!-- 定义目标对象 --> <bean id="orderDao" class="spring3.aop.demo4.OrderDao" /> <!-- 定义增强 --> <bean id="aroundAdvice" class="spring3.aop.demo4.MyAroundAdvice" /> <!-- 定义切点切面 --> <bean id="myPointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <!-- 定义表达式,规定哪些方法执行拦截 --> <!-- . 任意字符 * 任意个 .* 任意个任意字符 --> <!-- 对所有方法进行拦截 --> <!-- <property name="pattern" value=".*"/> --> <!-- 拦截指定类中以add开头的所有方法 --> <!-- <property name="pattern" value="spring3\.aop\.demo4\.OrderDao\.add.*"/> --> <!-- 拦截方法名包含add的方法 --> <!-- <property name="pattern" value=".*add.*"/> --> <!-- 多种格式的拦截:拦截方法名中包含add或find的方法 --> <property name="patterns" value=".*add.*,.*find.*" /> <!-- 应用增强 --> <property name="advice" ref="aroundAdvice" /> </bean> <!-- 定义生成代理对象 --> <bean id="orderDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 配置目标 --> <property name="target" ref="orderDao" /> <!-- 针对类代理 --> <property name="proxyTargetClass" value="true" /> <!-- 在目标应用上增强 --> <property name="interceptorNames" value="myPointcutAdvisor" /> </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" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 定义目标对象 --> <bean id="customerDao" class="spring3.aop.demo3.CustomerDaoImpl" /> <bean id="orderDao" class="spring3.aop.demo4.OrderDao" /> <!-- 定义增强 --> <bean id="beforeAdvice" class="spring3.aop.demo3.MyBeforeAdvice" /> <bean id="aroundAdvice" class="spring3.aop.demo4.MyAroundAdvice" /> <!-- 自动代理:按照Bean名称的代理 基于后处理Bean,后处理Bean不需要配置ID --> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <!-- 对bean名称以Dao结尾的进行自动代理 --> <property name="beanNames" value="*Dao" /> <!-- 定义通知类型 也可以指定多个 --> <property name="interceptorNames" value="beforeAdvice" /> </bean> </beans>SpringTest5 新建测试类
package spring3.aop.demo5; 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 spring3.aop.demo3.CustomerDao; import spring3.aop.demo4.OrderDao; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext2.xml") public class SpringTest5 { @Autowired @Qualifier("orderDao") private OrderDao OrderDao; @Autowired @Qualifier("customerDao") private CustomerDao CustomerDao; @Test public void demo1() { OrderDao.add(); OrderDao.delete(); CustomerDao.update(); } }运行结果如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 定义目标对象 --> <bean id="customerDao" class="spring3.aop.demo3.CustomerDaoImpl" /> <bean id="orderDao" class="spring3.aop.demo4.OrderDao" /> <!-- 定义增强 --> <bean id="beforeAdvice" class="spring3.aop.demo3.MyBeforeAdvice" /> <bean id="aroundAdvice" class="spring3.aop.demo4.MyAroundAdvice" /> <!-- 定义一个带有切点的切面 --> <bean id="mypointcutAdvisor" 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" /> </beans>SpringTest6 测试类
package spring3.aop.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; import spring3.aop.demo3.CustomerDao; import spring3.aop.demo4.OrderDao; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext3.xml") public class SpringTest6 { @Autowired @Qualifier("orderDao") private OrderDao orderDao; @Autowired @Qualifier("customerDao") private CustomerDao customerDao; @Test public void demo1() { orderDao.add(); orderDao.update(); orderDao.delete(); customerDao.add(); } }运行结果如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 开启AspectJ自动代理--> <aop:aspectj-autoproxy /> </beans>AspectJ表达式
package aop.aspectj.demo1; public class UserDao { public void add(){ System.out.println("添加用户"); } public int update(){ System.out.println("修改用户"); return 1; } public void delete(){ System.out.println("删除用户"); int d = 1/ 0; } public void find(){ System.out.println("查询用户"); } }MyAspect 注解实现AspectJ的切面
package aop.aspectj.demo1; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; /** * * 切面类:就是切点和增强的组合 * */ @Aspect public class MyAspect { @Before("execution(* aop.aspectj.demo1.UserDao.add(..))") public void before(JoinPoint joinPoint) { System.out.println("前置增强..." + joinPoint); } @AfterReturning(value = "execution(* aop.aspectj.demo1.UserDao.update(..))", returning = "returnVal") public void afterReturning(Object returnVal) { System.out.println("后置增强...方法的返回值" + returnVal); } @AfterThrowing(value = "MyAspect.myPointcut1()", throwing = "e") public void afterThrowing(Throwable e) { System.out.println("警告:出现异常了!!! " + e.getMessage()); } @After("MyAspect.myPointcut1()||MyAspect.myPointcut2()") public void after(){ System.out.println("最终通知..."); } @Pointcut("execution(* aop.aspectj.demo1.UserDao.delete(..))") public void myPointcut1() { } @Pointcut("execution(* aop.aspectj.demo1.UserDao.find(..))") public void myPointcut2() { } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 自动生成代理 底层就是AnnotationAwareAspectJAutoProxyCreator --> <aop:aspectj-autoproxy /> <bean id="userDao" class="aop.aspectj.demo1.UserDao" /> <bean id="myAspect" class="aop.aspectj.demo1.MyAspect" /> </beans>编写测试类 SpringTest1
package aop.aspectj.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 SpringTest1 { @Autowired @Qualifier("userDao") private UserDao userDao; @Test public void demo1() { userDao.add(); userDao.update(); userDao.find(); userDao.delete(); } }运行结果如下:
package aop.aspectj.demo2; public class ProductDao { public int add() { System.out.println("添加商品..."); int d = 10 / 0; return 100; } public void update() { System.out.println("修改商品..."); } public void delete() { System.out.println("删除商品..."); } public void find() { System.out.println("查询商品..."); } }MyAspectXML 切面类
package aop.aspectj.demo2; import org.aspectj.lang.ProceedingJoinPoint; /** * 切面类 */ public class MyAspectXML { public void before() { System.out.println("前置通知..."); } public void afterReturning(Object returnVal) { System.out.println("后置通知...返回值:" + returnVal); } public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕前增强..."); Object result = proceedingJoinPoint.proceed(); System.out.println("环绕后增强..."); return result; } public void afterThrowing(Throwable e) { System.out.println("异常通知..." + e.getMessage()); } public void after() { 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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 定义被增强的类 --> <bean id="productDao" class="aop.aspectj.demo2.ProductDao" /> <!-- 定义切面 --> <bean id="myAspectXML" class="aop.aspectj.demo2.MyAspectXML" /> <!-- 定义AOP配置 --> <aop:config> <!-- 定义切点 --> <aop:pointcut expression="execution(* aop.aspectj.demo2.ProductDao.add(..))" id="myPointcut"/> <aop:pointcut expression="execution(* aop.aspectj.demo2.ProductDao.delete(..))" id="myPointcut2"/> <!-- 配置Aspect增强类 --> <aop:aspect ref="myAspectXML"> <!-- 前置通知 --> <aop:before method="before" pointcut="execution(* aop.aspectj.demo2.ProductDao.update(..))" /> <!-- 后置通知 --> <aop:after-returning method="afterReturning" pointcut-ref="myPointcut" returning="returnVal"/> <!-- 环绕通知 --> <aop:around method="around" pointcut-ref="myPointcut2"/> <!-- 异常通知 --> <aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut" throwing="e"/> <!-- 最终通知 --> <aop:after method="after" pointcut-ref="myPointcut"/> </aop:aspect> </aop:config> </beans>SpringTest2 测试类
package aop.aspectj.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 SpringTest2 { @Autowired @Qualifier("productDao") private ProductDao productDao; @Test public void demo1() { productDao.update(); productDao.delete(); productDao.find(); productDao.add(); } }运行结果如下
// JDBC模板 依赖连接池获得数据库连接,所有必须先构造连接池 DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///spring"); dataSource.setUsername("root"); dataSource.setPassword("123"); // 创建JDBC模板 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); // 建表SQL语句 String sql = "create table customers(id int primary key auto_increment,name varchar(20))"; jdbcTemplate.execute(sql);
<!-- 配置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="123"/> </bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql:///spring"></property> <property name="username" value="root"></property> <property name="password" value="123"></property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql:///spring"></property> <property name="user" value="root"></property> <property name="password" value="123"></property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 引入第三方 properties配置 --> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <!-- ${key} 可以读取properties文件中配置 key对应value --> <property name="driverClass" value="${jdbc.driver}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> </beans> ================================================== <context:property-placeholder> 可以写为 <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:jdbc.properties"></property> </bean>
### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.err log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to file mylog.log ### log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=c\:mylog.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### set log levels - for more verbose logging change 'info' to 'debug' ### log4j.rootLogger=info, stdoutapplicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 配置Spring默认连接池 --> <bean id="dataSource_default" 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_dbcp" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <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"></property> </bean> --> <context:property-placeholder location="classpath:jdbc.properties" /> <!-- 配置C3P0连接池 --> <!-- <bean id="dataSource_c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driver}" /> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="user" value="${jdbc.user}" /> <property name="password" value="${jdbc.password}" /> </bean> --> <!-- 定义JDBC模板 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource_default" /> </bean> </beans>SpringTest1
package spring3.jdbctemplate.demo1; import javax.annotation.Resource; 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.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class SpringTest1 { @Autowired @Qualifier("jdbcTemplate") JdbcTemplate jdbcTemplate; @Test // 手动配置Spring自带的数据源 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))"); } @Test public void demo2() { jdbcTemplate.execute("insert into user values(null,'spring_dataSource')"); } }运行demo1
package spring3.jdbctemplate.demo2; 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; } @Override public String toString() { return "User [id=" + id + ", name=" + name + "]"; } }UserDao
package spring3.jdbctemplate.demo2; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import org.springframework.jdbc.core.RowMapper; 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); } public void delete(User user) { String sql = "delete from user where id= ?"; this.getJdbcTemplate().update(sql, user.getId()); } public int findCount() { String sql = "select count(*) from user"; return this.getJdbcTemplate().queryForInt(sql); } public String findNameById(int id) { String sql = "select name from user where id = ?"; return this.getJdbcTemplate().queryForObject(sql, String.class, id); } public User findById(int id) { String sql = "select * from user where id = ?"; return this.getJdbcTemplate().queryForObject(sql, new UserRowMapper(), id); } public List<User> findAll() { String sql = "select * from user"; return this.getJdbcTemplate().query(sql, new UserRowMapper()); } class UserRowMapper implements RowMapper<User> { /** * rs: 结果集 rowNum: 行号 */ @Override public User mapRow(ResultSet rs, int rowNum) throws SQLException { User user = new User(); user.setId(rs.getInt("id")); user.setName(rs.getString("name")); return user; } } }在applicationContext.xml文件中添加如下配置
<bean id="userDao" class="spring3.jdbctemplate.demo2.UserDao"> <property name="jdbcTemplate" ref="jdbcTemplate" /> </bean>测试SpringTest2
package spring3.jdbctemplate.demo2; import java.util.List; 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 SpringTest2 { @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); } @Test public void demo4() { int count = userDao.findCount(); System.out.println(count); } @Test public void demo5() { String name = userDao.findNameById(3); System.out.println(name); } @Test public void demo6() { User user = userDao.findById(3); System.out.println(user); } @Test public void demo7() { List<User> list = userDao.findAll(); for (User user : list) { System.out.println(user); } } }由代码和测试可以发现 JDBCTemplate和DBUtils很类似