框架 day37 Spring3,AOP,代理模式(动态/CGLIB/工厂bean),传统AOP,AspectJ框架(基于xml/注解),切入点表达式,jdbcTemplate

1     AOP

1.1   什么是AOP

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

* AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码

* 经典应用:性能监视、事务管理、安全检查、缓存等

* Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码

* AspectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入

1.2   aop实现原理

* aop 底层采用是代理机制

* 接口 + 实现类:有接口,采用JDK动态代理。

* 实现类:只有实现类,没有接口,采用CGLIB 字节码增强

1.3   aop相关术语(掌握)

* Target : 目标类,需要被增强的类。

* JoinPoint:连接点,目标类上需要被增强的方法。(这些方法可以被增强,也可能不增强)

* PointCut:切入点,被增强的连接点。(已经增强了)

切入点可以理解为是连接点一个子集。

* Advice :增强/通知,增强的方法。

* weaving:织入,将切入点和通知结合,生成代理类过程。

* Proxy:代理类

* Aspect:切面,切入点和通知结合(切入点和 通知点 多点形成面)

特殊情况:一个切入点和 一个通知

* Introduction(引介):特殊的通知,可以对类增强,添加方法或字段。(知道)

2     代理模式-手动方式:(了解)

2.1   动态代理:接口+实现类

* 步骤一:目标类,接口+实现类

public interface UserService {

	public void addUser();

	public void updateUser();

}
public class UserServiceImpl implements UserService {

	@Override
	public void addUser() {
		System.out.println("jdk add user");
	}

	@Override
	public void updateUser() {
		System.out.println("jdk update user");
	}

}

* 步骤二:编写切面类

public class MyAspect {

	public void before(){
		System.out.println("前");
	}
	public void after(){
		System.out.println("后");
	}

}

* 步骤三:编写工厂,生成代理类,将目标类与切面类结合。使用JDK的动态代理

public class MyFactory {

	/**
	 * 工厂生产代理类,目的:将目标类(切入点)和切面类(通知) 结合。
	 * @return
	 */
	public static UserService createService() {
		//1 创建目标类
		final UserService userService = new UserServiceImpl();
		//2 创建切面类
		final MyAspect myAspect = new MyAspect();
		//3 使用jdk 动态代理生产代理类
		UserService proxyService = (UserService)Proxy.newProxyInstance(
							MyFactory.class.getClassLoader(),
							userService.getClass().getInterfaces(),
							new InvocationHandler(){
								// 代理类每一个方法执行时,都将调用处理类的invoke方法
								@Override
								public Object invoke(Object proxy,
										Method method, Object[] args)
										throws Throwable {
									// 执行前通知
									myAspect.before();

									//执行目标类的相应方法
									Object obj = method.invoke(userService, args);

									// 执行后通知
									myAspect.after();

									return obj;  //返回方法返回值
								}
							});

		return proxyService; //返回代理类
	}

}

* 步骤四:测试

	@Test
	public void demo02(){
		UserService userService = MyFactory.createService();
		userService.addUser();
		userService.updateUser();
	}

2.2   CGLIB代理:实现类

* cglib:字节码增强工具,一般框架都使用。只要有类就可以增强。

* 使用需要到导入jar包

核心:cglib-2.2.jar

依赖:asm...jar

spring已经将cglib 和 asm 整合 spring.core..jar中。

* 步骤一:提供目标类,没有接口

public class UserServiceImpl{

	public void addUser() {
		System.out.println("cglib add user");
	}

	public void updateUser() {
		System.out.println("cglib update user");
	}

}

* 步骤二:提供切面类

public class MyAspect {

	public void before(){
		System.out.println("前");
	}
	public void after(){
		System.out.println("后");
	}

}

* 步骤三:编写工厂,使用cglib生成代理类

/**
	 * 工厂生产代理类,目的:将目标类(切入点)和切面类(通知) 结合。
	 * @return
	 */
	public static UserServiceImpl createService() {
		//1 创建目标类
		final UserServiceImpl userService = new UserServiceImpl();
		//2 创建切面类
		final MyAspect myAspect = new MyAspect();
		//3 使用cglib 创建 代理类 , cglib 运行时,动态创建目标类子类(代理类) , 所以目标类不能使final的  public final class ...
		// 3.1 创建核心类
		Enhancer enhancer = new Enhancer();
		// 3.2 设置父类
		enhancer.setSuperclass(userService.getClass());
		// 3.3 代理类方法将调用回调函数,等效JDK InvocationHandler
		// ** 接口:Callback,子接口 MethodInterceptor 对方法进行增强的。
		enhancer.setCallback(new MethodInterceptor(){
			@Override
			// 前三个参数:与jdk 动态代理 invoke相同的
			// 参数4:methodProxy , 方法代理
			public Object intercept(Object proxy, Method method, Object[] args,
					MethodProxy methodProxy) throws Throwable {
				//1 切面的类 前通知
				myAspect.before();
				//2 目标类的方法
				Object obj = method.invoke(userService, args);  //执行目标类的方法
				methodProxy.invokeSuper(proxy, args); //执行代理类(子类)的父类方法 (父类就是目标类)

				//3 切面类 后通知
				myAspect.after();

				return obj;
			}
		});
		// 3.4 创建代理类
		return (UserServiceImpl)enhancer.create();

	}

2.3   代理知识总结

*      Spring在运行期,生成动态代理对象,不需要特殊的编译器

*      Spring AOP的底层就是通过JDK动态代理CGLib动态代理技术 为目标Bean执行横向织入

1.若目标对象实现了若干接口,spring使用JDK的java.lang.reflect.Proxy类代理。

2.若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。

*       程序中应优先对接口创建代理,便于程序解耦维护

*       标记为final的方法,不能被代理,因为无法进行覆盖

? JDK动态代理,是针对接口生成子类,接口中方法不能使用final修饰

? CGLib 是针对目标类生产子类,因此类或方法 不能使final的

*      Spring只支持方法连接点,不提供属性连接

3     spring工厂bean,半自动(了解)

3.1   aop联盟通知类型

* 使用spring提供 FactoryBean创建代理对象,手动的获取代理对象。生成代理需要应用增强(通知),通知需要确定方法名称。spring规范规定通知类型,从而确定方法名称。

* aop联盟确定5中通知类型,spring对aop联盟进行支持。

前置通知org.springframework.aop.MethodBeforeAdvice

在目标方法执行前实施增强

后置通知org.springframework.aop.AfterReturningAdvice

在目标方法执行后实施增强

环绕通知org.aopalliance.intercept.MethodInterceptor【】

在目标方法执行前后实施增强

异常抛出通知org.springframework.aop.ThrowsAdvice

在方法抛出异常后实施增强

引介通知org.springframework.aop.IntroductionInterceptor(了解)

在目标类中添加一些新的方法和属性

环绕

try{

前置

//必须手动执行目标方法

后置

} catch(){

//异常抛出

}

3.2   使用代理工厂bean

3.2.1       导入jar包

spring: 4个核心 + 1个依赖

springaop联盟:com.springsource.org.aopalliance-1.0.0.jar

springaop 实现:spring-aop-3.2.2.RELEASE.jar

3.2.2       目标类和接口

public class UserServiceImpl implements UserService {

	@Override
	public void addUser() {
		System.out.println("factorybean add user");
	}

	@Override
	public void updateUser() {
		System.out.println("factorybean update user");
	}

}

3.2.3       编写切面类

* 必须遵循 aop联盟规范,通知需要实现相应接口

/**
 * 切面类,用于存放通知,使用的aop联盟规范,必须实现接口,从而确定方法名称(及spring如果执行通知)
 *
 */
public class MyAspect implements MethodInterceptor{

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		System.out.println("前");
		//环绕通知,必须手动的执行目标方法
		Object obj = mi.proceed();

		System.out.println("后");
		return obj;
	}

}

3.2.4       编写 spring配置

*  确定目标类 和切面类,通过spring提供ProxyFactoryBean生成代理类,将目标类和切面类进行结合。

通过属性注入的方式进行。

	<!-- 1 创建目标类 -->
	<bean id="userServiceId" class="com.itheima.b_factorybean.UserServiceImpl"></bean>
	<!-- 2创建切面类(通知) -->
	<bean id="myAspectId" class="com.itheima.b_factorybean.MyAspect"></bean>

	<!-- 3 生成代理对象,目的:将目标类与切面类结合
		* ProxyFactoryBean :生成一个特殊代理bean。
			* interfaces 确定接口,需要使用value
			* target 确定目标类,需要使用ref(对目标类的引用)
			* interceptorNames 确定通知所在类中名称,只需要名称不需要对象。需要使用value
			* optimize 确定是否使用cglib生成代理,true是,默认是false。
	-->
	<bean id="proxyServiceId" class="org.springframework.aop.framework.ProxyFactoryBean">
		<!-- 3.1 确定接口 -->
		<property name="interfaces" value="com.itheima.b_factorybean.UserService"></property>
		<!-- 3.2 确定目标类 -->
		<property name="target" ref="userServiceId"></property>
		<!-- 3.3 确定通知 ,使用切面类名称-->
		<property name="interceptorNames" value="myAspectId"></property>
		<!-- 3.4 强制使用cglib -->
		<property name="optimize" value="true"></property>
	</bean>

3.2.5       测试

@Test
	public void demo02(){
		//从工厂(spring)获得代理对象
		String xmlPath = "com/itheima/b_factorybean/beans.xml";
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);

		UserService userService = (UserService) applicationContext.getBean("proxyServiceId");
		userService.addUser();
		userService.updateUser();
	}

4     spring传统aop开发(掌握)

*    从spring容器获得目标类,进行aop配置从而让spring创建代理类。全自动过程

*    需添加aop命名空间

*    使用aspectj 切入点表达式,需要导入jar包

*    spring配置

<?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">
	<!-- 1 创建目标类 -->
	<bean id="userServiceId" class="com.itheima.c_aop.UserServiceImpl"></bean>
	<!-- 2创建切面类(通知) -->
	<bean id="myAspectId" class="com.itheima.c_aop.MyAspect"></bean>
	<!-- 3 spring 传统aop开发,使 通知 引用到 目标类切入点上
		* 添加aop命名空间
		* aop 编程 <aop:config>
		* <aop:pointcut> 用于声明切入点,确定目标类上的那些方法将被增强。
			id : 切入点名称
			expression : 用于编写切入点表达式 (aspectj 切入点表达式)
				execution(* com.itheima.c_aop.*.*(..))
				固定		返回值类型	包			类名	方法名	参数列表
		* <aop:advisor> 特殊的切面,只有一个切入点和一个通知
			advice-ref:一个通知引用
			pointcut-ref:一个切入点引用
	-->
	<aop:config>
		<aop:pointcut expression="execution(* com.itheima.c_aop.*.*(..))" id="myPointCut"/>
		<aop:advisor advice-ref="myAspectId" pointcut-ref="myPointCut"/>
	</aop:config>
</beans>

5     AspectJaop框架(掌握)

5.1   AspectJ介绍

*    AspectJ是一个基于Java语言的AOP框架

*     Spring2.0以后新增了对AspectJ切入点表达式支持

*     @Aspect是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面

新版本Spring框架,建议使用AspectJ方式来开发AOP

*    导入jar包:

aop联盟:com.springsource.org.aopalliance-1.0.0.jar

springaop支持:spring-aop-3.2.0.RELEASE.jar

aspect规范:com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

springaspect 支持:spring-aspects-3.2.0.RELEASE.jar

5.2   切入点表达式(掌握

1.execution:匹配方法的执行(常用)

格式execution(修饰符 返回值类型  包.类名.方法(参数) throws 异常)

1.1修饰符,表示方法的修饰符,一般省略。

1.2返回值类型

  String                                       表示返回String

void                                           表示没有返回值

*                                                 表示返回任意类型【】

1.3包

com.itheima.service                                         表示指定的包

com.itheima.crm.*.service                              表示crm的子模块,名称任意。

(例如:com.itheima.crm.user.service)

com.itheima.service..                                       表示service目录,及子目录

综合:com.itheima.crm.*.service..     -->       service / service.impl

1.4类名

UserService                            表示指定的类

*Service                                   表示以Service结尾

Test*                                         表示以Test开头

*                                                 表示任意类名

1.5方法名(与类名类似)

    addUser                                  表示指定方法

   add*                                         表示以add开头

*Do                                           表示以Do结尾

       *                                                表示任意

  1.6参数列表

()                                                 表示没有参数

(int)                                            表示一个参数int类型

(int,int)                                      表示两个参数int类型

(如果是java.lang包下的可以省略,其他都必须是全限定类名)

(..)                                              表示参数任意

1.7throws 异常,                          一般省略。

综合:execution(*com.itheima.crm.*.service..*.*(..)) ↓↓↓ 匹配↓↓↓

com.itheima.crm.user.service.impl.UserService.addUser(Useruser)

2.within:匹配包或子包中的方法(了解)

within(cn.itcast.aop..*)

3.this:匹配实现接口的代理对象中的方法(了解)

this(cn.itcast.aop.user.UserDAO)

4.target:匹配实现接口的目标对象中的方法(了解)

target(cn.itcast.aop.user.UserDAO)

5.args:匹配参数格式符合标准的方法(了解)

args(int,int)

6.bean(名称) ,匹配指定的bean(了解)

bean("userServiceId")

5.3   AspectJ规定通知类型

*    共6个,知道5个,掌握1个。

1.before:前置通知(应用:各种校验)

在方法执行前执行,如果通知抛出异常,阻止方法运行

2.afterReturning:后置通知(应用:常规数据处理)

方法正常返回后执行,如果方法中抛出异常,通知无法执行

必须在方法执行后才执行,所以可以获得方法的返回值。

3.around:环绕通知(应用:十分强大,可以做任何事情) 【】

方法执行前后分别执行,可以阻止方法的执行。要求必须手动的执行目标方法。

4.afterThrowing:抛出异常通知(应用:包装异常信息)

方法抛出异常后执行,如果方法没有抛出异常,无法执行

5.after:最终通知(应用:清理现场)

方法执行完毕后执行,无论方法中是否出现异常

环绕(around)

try{

//前置(before)

//手动执行目标类方法

//后置(afterReturning) --可以获得返回值

} catch(){

//抛出异常(afterThrowing)  --可以获得具体的异常信息

} finally{

//最终(after)

}

5.4   基于xml aspectj

*    aspectj通知类型 通过配置文件确定,没有具体接口。通知方法任意。

*    xml配置

>常用属性

?        pointcut:配置切入点表达式

?        pointcut-ref:配置切入点引用对象

?        method:配置切入点执行的通知方法

>JoinPoint连接点的信息

 接口:org.aspectj.lang.JoinPoint

?        目标对象:getTarget()

?        获得方法签名:getSignature()

?        获得方法名称:getSignature().getName()

?        获得实际参数:getArgs()

?        获得当前指定方法的类型:getKind()

?        method-execution 方法执行、

?        constructor-execution构造方法执行

?        field-get get方法

<?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">
	<!-- 1 创建目标类 -->
	<bean id="userServiceId" class="com.itheima.d_aspect.a_xml.UserServiceImpl"></bean>
	<!-- 2创建切面类(通知) -->
	<bean id="myAspectId" class="com.itheima.d_aspect.a_xml.MyAspect"></bean>
	<!-- 3 aspect 编程
		<aop:config> aop 编程
			proxy-target-class 如果设置true表示强转使用cglib代理
		<aop:aspect> aspect编程
			ref 用于确定切面类,从而确定通知

	-->
	<aop:config>
		<aop:aspect ref="myAspectId">
			<!-- 声明切入点,确定目标类上哪些方法将成为切入点,需要被增强 -->
			<aop:pointcut expression="execution(* com.itheima.d_aspect.a_xml.*.*(..))" id="myPointcut"/>
			<!-- 声明通知方式
				1.前置通知
					<aop:before method=""/>
						method 切面类中具体的方法名称
							方法可以有一个参数,类型: org.aspectj.lang.JoinPoint
							用于获得当前执行方法的具体详情
						pointcut-ref 切入点的引用(大家共享)
						pointcut 给当前前置通知编写切入点表达式(自己使用)
					<aop:before method="myBefore" pointcut-ref="myPointcut"/>
				2.后置通知
					目标方法执行之后才执行,可以获得返回值。
					returning 用于设置通知第二个参数的名称,类型:Object
						public void myAfterReturning(JoinPoint joinPoint,Object ret){
						<aop:after-returning returning="ret"/>
					<aop:after-returning method="myAfterReturning" pointcut-ref="myPointcut" returning="ret"/>
				3.环绕通知
					环绕通知方法要求
						1.返回类型Object
						2.必须抛出异常 throws Throwable
						3.必须接受一个参数,类型 ProceedingJoinPoint
						4.方法体中手动执行目标方法,Object obj = joinPoint.proceed();
					<aop:around method="myAround" pointcut-ref="myPointcut"/>
				4.抛出异常
					目标方法出现异常时执行,如果没有异常忽略。
					throwing 设置第二个参数名称,获得具体的异常信息的。类型:Throwable
						public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
					<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointcut" throwing="e"/>
				5.最终
					无论是否有异常,都将执行
			-->
			<aop:after method="myAfter" pointcut-ref="myPointcut" />
		</aop:aspect>
	</aop:config>
</beans>

*    切面类

/**
 * 切面类,存放所有通知,aspectj 没有提供接口,所有的通知都是通过配置文件确定。
 */
public class MyAspect {

	public void myBefore(JoinPoint joinPoint){
		System.out.println("前置通知 : " + joinPoint.getSignature().getName());
	}

	public void myAfterReturning(JoinPoint joinPoint,Object ret){
		System.out.println("后置通知 : " + ret );
	}

	public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
		System.out.println("前");
		//手动执行目标类
		Object obj = joinPoint.proceed();

		System.out.println("后");
		return obj;
	}

	public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
		System.out.println("抛出异常 : " + e.getMessage());
	}

	public void myAfter(JoinPoint joinPoint){
		System.out.println("最终");
	}

}

5.5   基于注解 aspectJ

*    步骤一:将切面类配置给spring

@Component

public class MyAspect {

*    步骤二:将切面类声明成切面

@Component

@Aspect

public class MyAspect {

*    步骤三:声明共有切入点

1.方法必须private,没有返回值,没有参数

2.之后使用将其当成方法调用。例如:@After("myPointcut()")

@Pointcut("execution(*com.itheima.d_aspect.b_annotation.*.*(..))")

privatevoid myPointcut(){}

*    步骤四:编写相应的通知

@Before 前置

@AfterReturning  后置,可以获得返回值,必须在注解中确定返回值参数名称。

@AfterThrowing 抛出异常,可以获得具体异常信息,必须在注解确定第二个参数名称

@Around 环绕

@After 最终

/**
 * 切面类,存放所有通知,aspectj 没有提供接口,所有的通知都是通过配置文件确定。
 */
@Component   //2.<bean id="myAspectId" class="com.itheima.d_aspect.b_annotation.MyAspect"></bean>
@Aspect		//3.1 <aop:aspect ref="myAspectId">  让切面类形成切面 (通知和切入点结合)
public class MyAspect {

	//@Before("execution(* com.itheima.d_aspect.b_annotation.*.*(..))")
	// 取代 <aop:before method="myBefore" pointcut="execution(* com.itheima.d_aspect.b_annotation.*.*(..))"/>
	public void myBefore(JoinPoint joinPoint){
		System.out.println("前置通知 : " + joinPoint.getSignature().getName());
	}

	//@AfterReturning(value="execution(* com.itheima.d_aspect.b_annotation.*.*(..))",returning="ret")
	public void myAfterReturning(JoinPoint joinPoint,Object ret){
		System.out.println("后置通知 : " + ret );
	}

	//编写共有的切入点表达式
	@Pointcut("execution(* com.itheima.d_aspect.b_annotation.*.*(..))")
	private void myPointcut(){}

	//@Around("myPointcut()")
	public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
		System.out.println("前");
		//手动执行目标类
		Object obj = joinPoint.proceed();

		System.out.println("后");
		return obj;
	}
	//@AfterThrowing(value="myPointcut()",throwing="e")
	public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
		System.out.println("抛出异常 : " + e.getMessage());
	}

	@After("myPointcut()")
	public void myAfter(JoinPoint joinPoint){
		System.out.println("最终");
	}
}

*    步骤五:必须在xml中扫描注解和启用aop自动代理

<?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.xsd
       					   http://www.springframework.org/schema/aop
       					   http://www.springframework.org/schema/aop/spring-aop.xsd
       					   http://www.springframework.org/schema/context
       					   http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- 1 扫描 -->
	<context:component-scan base-package="com.itheima.d_aspect.b_annotation"></context:component-scan>
	<!-- 2 使aop注解生效 -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

6     JdbcTemplate

Spring支持持久模板

*    spring提供 用于操作数据库模板。类似:DbUtils。使用时必须设置数据源(DataSource)

*    数据源:DBCP、C3P0等

*    导入jar包:

dbcp

com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar

com.springsource.org.apache.commons.pool-1.5.3.jar

c3p0:  com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar

spring-jdbc  spring-jdbc-3.2.0.RELEASE.jar

spring-tx(transaction)  spring-tx-3.2.0.RELEASE.jar

数据库驱动:mysql-connector-java-5.1.22-bin.jar

6.1   创建数据库及表

create database spring_day02_db;
use spring_day02_db;
create table t_user(
  id int primary key auto_increment,
  username varchar(50),
  password varchar(32)
);
insert into t_user(username,password) values('jack','1234');

6.2   使用DBCP

回顾使用API连接

	@Test
	public void demo01(){
		//1 创建数据库
		BasicDataSource dataSource = new BasicDataSource();
		// 1.1 驱动
		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		// 1.2 url
		dataSource.setUrl("jdbc:mysql://localhost:3306/spring_day02_db");
		// 1.3 user
		dataSource.setUsername("root");
		// 1.4 password
		dataSource.setPassword("1234");

		//2 创建模板
		JdbcTemplate jdbcTemplate = new JdbcTemplate();
		// 2.1 设置数据源
		jdbcTemplate.setDataSource(dataSource);

		//3 录入数据
		jdbcTemplate.update("insert into t_user(username,password) values(?,?)", "rose","1234");

	}

}

*    配置数据源,配置模板,dao直接使用模板。

<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">

	<!--1  配置数据源 -->
	<bean id="dataSourceId" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
		<property name="url" value="jdbc:mysql://localhost:3306/spring_day02_db"></property>
		<property name="username" value="root"></property>
		<property name="password" value="1234"></property>
	</bean>

	<!-- 2 配置模板,需要数据源 -->
	<bean id="jdbcTemplateId" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSourceId"></property>
	</bean>

	<!--3  配置dao,需要模板 -->
	<bean id="userDaoId" class="com.itheima.e_jdbc.b_dbcp.UserDao">
		<property name="jdbcTemplate" ref="jdbcTemplateId"></property>
	</bean>	

6.3   使用C3P0

*    dao之后继承 JdbcDaoSupport,spring直接给dao注入数据源DataSource即可,JdbcDaoSupport底层自动进行模板创建

c3p0配置

	<!--1  配置数据源 c3p0 -->
	<bean id="dataSourceId" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_day02_db"></property>
		<property name="user" value="root"></property>
		<property name="password" value="1234"></property>
	</bean>

	<!-- 2 配置模板,需要数据源
	<bean id="jdbcTemplateId" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSourceId"></property>
	</bean>
	-->

	<!--3  配置dao,需要模板
		* 将数据源 datasource注入给dao,继承JdbcDaoSupport 提供setDataSource,且此方法中将自动的创建模板。
	-->
	<bean id="userDaoId" class="com.itheima.e_jdbc.c_c3p0.UserDao">
		<property name="dataSource" ref="dataSourceId"></property>
	</bean>

dao使用(继承JdbcDaoSupport)

public class UserDao extends JdbcDaoSupport{

	public void save(String username,String password){
		this.getJdbcTemplate().update("insert into t_user(username,password) values(?,?)", username,password);
	}

	public User find(int id) {
		// queryForObject 查询一个结果,如果没有结果抛异常。
		String sql = "select * from t_user where id = ?";
		return this.getJdbcTemplate().queryForObject(sql, ParameterizedBeanPropertyRowMapper.newInstance(User.class), id);
	}

}

6.4   使用properties

*    将连接数据的具体参数配合到properties文件,由spring加载properties,并在spring配置文件中使用。

jdbcinfo.properties

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/spring_day02_db
jdbc.user=root
jdbc.password=1234

配置

<?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.xsd
       					   http://www.springframework.org/schema/aop
       					   http://www.springframework.org/schema/aop/spring-aop.xsd
       					   http://www.springframework.org/schema/context
       					   http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- 0 加载properties文件
		location 用于指定配置文件位置
			classpath: 固定的字符串表示从 src下获取
		在spring 配置文件中,就可以通过${key} 方式获取
	-->
	<context:property-placeholder location="classpath:com/itheima/e_jdbc/d_properties/jdbcinfo.properties"/>

	<!--1  配置数据源 c3p0 -->
	<bean id="dataSourceId" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${jdbc.driverClass}"></property>
		<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
		<property name="user" value="${jdbc.user}"></property>
		<property name="password" value="${jdbc.password}"></property>
	</bean>

	<!-- 2 配置模板,需要数据源
	<bean id="jdbcTemplateId" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSourceId"></property>
	</bean>
	-->

	<!--3  配置dao,需要模板
		* 将数据源 datasource注入给dao,继承JdbcDaoSupport 提供setDataSource,且此方法中将自动的创建模板。
	-->
	<bean id="userDaoId" class="com.itheima.e_jdbc.d_properties.UserDao">
		<property name="dataSource" ref="dataSourceId"></property>
	</bean>
</beans>

6.5   JdbcTemplate  API

*    update进行 增删改操作

*    queryForObject  查询一个

*    query  查询所有

*    queryForInt查询一个整形(分页)

public class UserDao extends JdbcDaoSupport{

	public void save(String username,String password){
		this.getJdbcTemplate()
		.update("insert into t_user(username,password) values(?,?)"
		, username,password);
	}

	public User find(int id) {
		// queryForObject 查询一个结果,如果没有结果抛异常。
		String sql = "select * from t_user where id = ?";
		return this.getJdbcTemplate()
		.queryForObject(sql, ParameterizedBeanPropertyRowMapper
		.newInstance(User.class), id);
	}

	public List<User> findAll() {
		String sql = "select * from t_user";
		return this.getJdbcTemplate()
		.query(sql, ParameterizedBeanPropertyRowMapper
		.newInstance(User.class));
	}

}
时间: 2024-12-14 06:17:06

框架 day37 Spring3,AOP,代理模式(动态/CGLIB/工厂bean),传统AOP,AspectJ框架(基于xml/注解),切入点表达式,jdbcTemplate的相关文章

设计模式--5.4 代理模式-动态代理

1.动态代理 (1)动态代理,是实现阶段不关心代理谁,而在运行阶段才指定代理哪一个对象.相对的说,上面两种 普通代理和强制代理,都是通过写代理类来获取代理,这种是静态代理. (2)区别:静态代理,需要写代理类,在代理之前要知道我代理的是哪个类: (3)类图 2.代码 接口类 package com.design.代理模式.动态代理; public interface IGamePlayer { void login(String username , String pwd); void kill

框架 day36 Spring3 入门,DI依赖注入,装配bean基于xml/注解, 整合Junit4,配置约束自动提示

1 什么是spring 1.1官网 spring.io 1.2介绍 Spring的核心是控制反转(IoC)和面向切面(AOP). IoC(Inverse of Control 反转控制) AOP(Aspect Oriented Programming 面向切面编程为内核) 简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架. *轻量级:依赖其他内容较小,使用资源消耗也少.对比:EJB 重量级 *分层:经典三层体系架构,spring 提供解决方案

设计模式之--代理模式(动态代理)

JDK 提供的动态代理的两个相关的类:InvocationHandler 和 Proxy 一:InvocationHandler  InvocationHandler 接口只提供了一个接口方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; 1 Object proxy 被代理的对象 2 Method method 被代理对象的实现方法 3 Object[] args 被代理对象

设计模式之代理模式(动态代理)

跟之前上一篇静态代理的差不多.这个是在执行的时候动态的产生代理对象,开始是不知道具体的代理对象,是传入具体对象,就产生该具体对象的代理对象.而之前的静态代理是预知要传入的具体对象交给哪一个代理对象执行. 代码实现. 首先定义抽象角色,他是代理对象和具体对象的共同接口.可以是接口,也可以是抽象类. //抽象角色 定义的是一种类型 具有某种共同行为的类型 public interface ProxyInterface{ //定义行为,代理对象和具体对象的共同行为 public void run();

代理模式-静态代理与动态代理

简介 首先感谢沽泡学院 tom 老师 代理模式是一种结构型模式 代理模式就是代理对象帮被代理对象处理一些问题, 类似中介, 客户只要结果, 中介怎么搞是他的事儿, 他可能再处理过程中赚外快什么的 代理模式的应用: spring中的aop, 日常工作中记录日志, 统计时间,权限控制等 这里我们使用一个客户端代理访问google举例, 具体细节可能不合适, 意会.意会.意会... 静态代理 /** * 一个服务器接口, 服务器有很多功能, 可以用来路由, 建站等... */ public inter

代理模式应用-AOP事务(转)

https://jinnianshilongnian.iteye.com/blog/14872351.预备知识 aop概念请参考[http://www.iteye.com/topic/1122401]和[http://jinnianshilongnian.iteye.com/blog/1418596] spring的事务管理,请参考[http://jinnianshilongnian.iteye.com/blog/1441271] 使用AOP 代理后的方法调用执行流程,如图所示 也就是说我们首先

Java-马士兵动态代理模式

Java-马士兵动态代理模式 模拟jdk的动态代理的实现原理, 这些东西没有必要写出来,写项目的时候用不上,主要是面试和理解原理: ? 有些工具可以直接生成二进制码,没有必要生成文件. 代理模式-聚合与继承方式比较 参考地址:http://www.cnblogs.com/shamgod/p/4591782.html ? 一.概述 1.目标:要在Tank的move()方法做时间代理及日志代理(可以设想以后还要增加很多代理处理),且代理间的顺序可活更换 2.思路: (1)聚合:代理类聚合了被代理类,

模式的秘密-代理模式(2)-JDK动态代理

代理模式-动态代理 (1) (2) 代码实践动态代理: 第一步:被代理类的接口: package com.JdkProxy; public interface Moveable { void move(); } 第二步:被代理类: package com.JdkProxy; import java.util.Random; public class Car implements Moveable { @Override public void move() { //实现开车 try { Thre

Java的三种代理模式简述

本文着重讲述三种代理模式在java代码中如何写出,为保证文章的针对性,暂且不讨论底层实现原理,具体的原理将在下一篇博文中讲述. 代理模式是什么 代理模式是一种设计模式,简单说即是在不改变源码的情况下,实现对目标对象的功能扩展. 比如有个歌手对象叫Singer,这个对象有一个唱歌方法叫sing(). 1 public class Singer{ 2 public void sing(){ 3 System.out.println("唱一首歌"); 4 } 5 } 假如你希望,通过你的某种