Note_JavaWeb_Spring_尚硅谷

常用Api

spring-1

beans-annotation.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-4.0.xsd">

<!-- 配置自动扫描的包: 需要加入 aop 对应的 jar 包 -->

<context:component-scan base-package="com.atguigu.spring.annotation.generic"></context:component-scan>

</beans>

beans.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:util="http://www.springframework.org/schema/util"

xmlns:p="http://www.springframework.org/schema/p"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

property

<!-- 配置一个 bean -->

<bean id="helloWorld" class="com.atguigu.spring.helloworld.HelloWorld">

<!-- 为属性赋值 -->

<property name="user" value="Jerry"></property>

</bean>

<!-- 配置一个 bean -->

<bean id="helloWorld2" class="com.atguigu.spring.helloworld.HelloWorld">

<!-- 为属性赋值 -->

<!-- 通过属性注入: 通过 setter 方法注入属性值 -->

<property name="user" value="Tom"></property>

</bean>

constructor-arg

<!-- 通过构造器注入属性值 -->

<bean id="helloWorld3" class="com.atguigu.spring.helloworld.HelloWorld">

<!-- 要求: 在 Bean 中必须有对应的构造器.  -->

<constructor-arg value="Mike"></constructor-arg>

</bean>

<!-- 若一个 bean 有多个构造器, 如何通过构造器来为 bean 的属性赋值 -->

<!-- 可以根据 index 和 value 进行更加精确的定位. (了解) -->

<bean id="car" class="com.atguigu.spring.helloworld.Car">

<constructor-arg value="KUGA" index="1"></constructor-arg>

<constructor-arg value="ChangAnFord" index="0"></constructor-arg>

<constructor-arg value="250000" type="float"></constructor-arg>

</bean>

<bean id="car2" class="com.atguigu.spring.helloworld.Car">

<constructor-arg value="ChangAnMazda"></constructor-arg>

<!-- 若字面值中包含特殊字符, 则可以使用 DCDATA 来进行赋值. (了解) -->

<constructor-arg>

<value><![CDATA[<ATARZA>]]></value>

</constructor-arg>

<constructor-arg value="180" type="int"></constructor-arg>

</bean>

<!-- 配置 bean -->

<bean id="dao5" class="com.atguigu.spring.ref.Dao"></bean>

ref

<bean id="service" class="com.atguigu.spring.ref.Service">

<!-- 通过 ref 属性值指定当前属性指向哪一个 bean! -->

<property name="dao" ref="dao5"></property>

</bean>

内部 bean

<!-- 声明使用内部 bean -->

<bean id="service2" class="com.atguigu.spring.ref.Service">

<property name="dao">

<!-- 内部 bean, 类似于匿名内部类对象. 不能被外部的 bean 来引用, 也没有必要设置 id 属性 -->

<bean class="com.atguigu.spring.ref.Dao">

<property name="dataSource" value="c3p0"></property>

</bean>

</property>

</bean>

设置级联属性

<bean id="action" class="com.atguigu.spring.ref.Action">

<property name="service" ref="service2"></property>

<!-- 设置级联属性(了解) -->

<property name="service.dao.dataSource" value="DBCP2"></property>

</bean>

null

<bean id="dao2" class="com.atguigu.spring.ref.Dao">

<!-- 为 Dao 的 dataSource 属性赋值为 null, 若某一个 bean 的属性值不是 null, 使用时需要为其设置为 null(了解) -->

<property name="dataSource"><null/></property>

</bean>

list

<!-- 装配集合属性 -->

<bean id="user" class="com.atguigu.spring.helloworld.User">

<property name="userName" value="Jack"></property>

<property name="cars">

<!-- 使用 list 元素来装配集合属性 -->

<list>

<ref bean="car"/>

<ref bean="car2"/>

</list>

</property>

</bean>

util:list

<!-- 声明集合类型的 bean -->

<util:list id="cars">

<ref bean="car"/>

<ref bean="car2"/>

</util:list>

<bean id="user2" class="com.atguigu.spring.helloworld.User">

<property name="userName" value="Rose"></property>

<!-- 引用外部声明的 list -->

<property name="cars" ref="cars"></property>

</bean>

p:

<bean id="user3" class="com.atguigu.spring.helloworld.User"

p:cars-ref="cars" p:userName="Titannic"></bean>

parent

<!-- bean 的配置能够继承吗 ? 使用 parent 来完成继承 -->

<bean id="user4" parent="user" p:userName="Bob"></bean>

<bean id="user6" parent="user" p:userName="维多利亚"></bean>

depends-on

<!-- 测试 depents-on -->

<bean id="user5" parent="user" p:userName="Backham" depends-on="user6"></bean>

</beans>

beans-auto.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-4.0.xsd">

<!-- 自动装配: 只声明 bean, 而把 bean 之间的关系交给 IOC 容器来完成 -->

<!--

byType: 根据类型进行自动装配. 但要求 IOC 容器中只有一个类型对应的 bean, 若有多个则无法完成自动装配.

byName: 若属性名和某一个 bean 的 id 名一致, 即可完成自动装配. 若没有 id 一致的, 则无法完成自动装配

-->

<!-- 在使用 XML 配置时, 自动转配用的不多. 但在基于 注解 的配置时, 自动装配使用的较多.  -->

<bean id="dao" class="com.atguigu.spring.ref.Dao">

<property name="dataSource" value="C3P0"></property>

</bean>

Scope : prototype/ singleton

<!-- 默认情况下 bean 是单例的! -->

<!-- 但有的时候, bean 就不能使单例的. 例如: Struts2 的 Action 就不是单例的! 可以通过 scope 属性来指定 bean 的作用域 -->

<!--

prototype: 原型的. 每次调用 getBean 方法都会返回一个新的 bean. 且在第一次调用 getBean 方法时才创建实例

singleton: 单例的. 每次调用 getBean 方法都会返回同一个 bean. 且在 IOC 容器初始化时即创建 bean 的实例. 默认值

-->

<bean id="dao2" class="com.atguigu.spring.ref.Dao" scope="prototype"></bean>

autowire

<bean id="service" class="com.atguigu.spring.ref.Service" autowire="byName"></bean>

<bean id="action" class="com.atguigu.spring.ref.Action" autowire="byType"></bean>

context:property-placeholder

<!-- 导入外部的资源文件 -->

<context:property-placeholder location="classpath:db.properties"/>

dataSource

<!-- 配置数据源 -->

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

<property name="user" value="${jdbc.user}"></property>

<property name="password" value="${jdbc.password}"></property>

<property name="driverClass" value="${jdbc.driverClass}"></property>

<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>

<property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>

<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>

</bean>

<!-- 测试 SpEL: 可以为属性进行动态的赋值(了解) -->

<bean id="girl" class="com.atguigu.spring.helloworld.User">

<property name="userName" value="周迅"></property>

</bean>

init-method/destroy-method

<bean id="boy" class="com.atguigu.spring.helloworld.User" init-method="init" destroy-method="destroy">

<property name="userName" value="高胜远"></property>

<property name="wifeName" value="#{girl.userName}"></property>

</bean>

bean 后置处理器

<!-- 配置 bean 后置处理器: 不需要配置 id 属性, IOC 容器会识别到他是一个 bean 后置处理器, 并调用其方法 -->

<bean class="com.atguigu.spring.ref.MyBeanPostProcessor"></bean>

factory-method

<!-- 通过工厂方法的方式来配置 bean -->

<!-- 1. 通过静态工厂方法: 一个类中有一个静态方法, 可以返回一个类的实例(了解) -->

<!-- 在 class 中指定静态工厂方法的全类名, 在 factory-method 中指定静态工厂方法的方法名 -->

<bean id="dateFormat" class="java.text.DateFormat" factory-method="getDateInstance">

<!-- 可以通过 constructor-arg 子节点为静态工厂方法指定参数 -->

<constructor-arg value="2"></constructor-arg>

</bean>

<!-- 2. 实例工厂方法: 先需要创建工厂对象, 再调用工厂的非静态方法返回实例(了解) -->

<!-- ①. 创建工厂对应的 bean -->

<bean id="simpleDateFormat" class="java.text.SimpleDateFormat">

<constructor-arg value="yyyy-MM-dd hh:mm:ss"></constructor-arg>

</bean>

<!-- ②. 有实例工厂方法来创建 bean 实例 -->

<!-- factory-bean 指向工厂 bean, factory-method 指定工厂方法(了解) -->

<bean id="datetime" factory-bean="simpleDateFormat" factory-method="parse">

<!-- 通过 constructor-arg 执行调用工厂方法需要传入的参数 -->

<constructor-arg value="1990-12-12 12:12:12"></constructor-arg>

</bean>

<!-- 配置通过 FactroyBean 的方式来创建 bean 的实例(了解) -->

<bean id="user" class="com.atguigu.spring.ref.UserBean"></bean>

</beans>

db.properties

jdbc.user=root

jdbc.password=1230

jdbc.driverClass=com.mysql.jdbc.Driver

jdbc.jdbcUrl=jdbc:mysql:///test

jdbc.initPoolSize=5

jdbc.maxPoolSize=10

spring-2

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

<!--

1. 默认情况下, IOC 容器中的 bean 是单例的! 若对象是单例的, 则在创建 IOC 容器时即创建 bean 的实例, 并对 bean 的属性进行初始化.

2. 可以通过 bean 的 scope 属性来修改 bean 的作用域. 若取值为 prototype, 则 bean 为原型的: 每次向容器获取实例, 得到的都是一个新的对象.

而且, 不在创建 IOC 容器时创建 bean 的实例了.

3. IOC 容器中 bean 的生命周期:

3.1 一般地, 讨论 bean 的生命周期, 是建立在 bean 是单例的基础上的.

3.2 可以为 bean 指定 init 和 destroy 方法

3.3 还可以通过 bean 的后置处理器来更加丰富 bean 的生命周期方法(面试时.).

-->

<bean id="helloWorld"

class="com.atguigu.spring.helloworld.HelloWorld"

scope="singleton"

init-method="init"

destroy-method="destroy">

<property name="userName" value="atguigu"></property>

</bean>

<!--

1. 在 IOC 容器中配置 bean 之间的关联关系

-->

<bean id="userDao"

class="com.atguigu.spring.ref.UserDao"></bean>

<bean id="userService"

class="com.atguigu.spring.ref.UserService">

<property name="userDao" ref="userDao"></property>

</bean>

<bean id="userAction"

class="com.atguigu.spring.ref.UserAction">

<property name="userService" ref="userService"></property>

</bean>

</beans>

applicationContext-aop.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"

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

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

<!-- 自动扫描的包 -->

<context:component-scan base-package="com.atguigu.spring.aop"></context:component-scan>

aop:aspectj-autoproxy

<!-- 使 AspectJ 的注解起作用 -->

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

applicationContext-annotation.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-4.0.xsd">

<!-- 配置自动扫描的包 -->

<context:component-scan base-package="com.atguigu.spring.ref"></context:component-scan>

</beans>

aop\ArithmeticCalculator.java

package com.atguigu.spring.aop;

public interface ArithmeticCalculator {

int add(int i, int j);

int sub(int i, int j);

int mul(int i, int j);

int div(int i, int j);

}

aop\ArithmeticCalculatorImpl.java

package com.atguigu.spring.aop;

import org.springframework.stereotype.Component;

@Component("arithmeticCalculator")

public class ArithmeticCalculatorImpl implements ArithmeticCalculator {

@Override

public int add(int i, int j) {

int result = i + j;

return result;

}

@Override

public int sub(int i, int j) {

int result = i - j;

return result;

}

@Override

public int mul(int i, int j) {

int result = i * j;

return result;

}

@Override

public int div(int i, int j) {

int result = i / j;

return result;

}

}

aop\ArithmeticCalculatorLoggingImpl.java

package com.atguigu.spring.aop;

public class ArithmeticCalculatorLoggingImpl implements ArithmeticCalculator {

@Override

public int add(int i, int j) {

System.out.println("The method add begins with [" + i + "," + j + "]");

int result = i + j;

System.out.println("The method add ends with " + result);

return result;

}

@Override

public int sub(int i, int j) {

System.out.println("The method sub begins with [" + i + "," + j + "]");

int result = i - j;

System.out.println("The method sub ends with " + result);

return result;

}

@Override

public int mul(int i, int j) {

System.out.println("The method mul begins with [" + i + "," + j + "]");

int result = i * j;

System.out.println("The method mul ends with " + result);

return result;

}

@Override

public int div(int i, int j) {

System.out.println("The method div begins with [" + i + "," + j + "]");

int result = i / j;

System.out.println("The method div ends with " + result);

return result;

}

}

aop\ArithmeticCalculatorLoggingProxy.java

package com.atguigu.spring.aop;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import java.util.Arrays;

public class ArithmeticCalculatorLoggingProxy {

//要代理的对象

private ArithmeticCalculator target;

public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target) {

super();

this.target = target;

}

//返回代理对象

public ArithmeticCalculator getLoggingProxy(){

ArithmeticCalculator proxy = null;

ClassLoader loader = target.getClass().getClassLoader();

Class [] interfaces = new Class[]{ArithmeticCalculator.class};

InvocationHandler h = new InvocationHandler() {

/**

* proxy: 代理对象。 一般不使用该对象

* method: 正在被调用的方法

* args: 调用方法传入的参数

*/

@Override

public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

String methodName = method.getName();

//打印日志

System.out.println("[before] The method " + methodName + " begins with " + Arrays.asList(args));

//调用目标方法

Object result = null;

try {

//前置通知

result = method.invoke(target, args);

//返回通知, 可以访问到方法的返回值

} catch (NullPointerException e) {

e.printStackTrace();

//异常通知, 可以访问到方法出现的异常

}

//后置通知. 因为方法可以能会出异常, 所以访问不到方法的返回值

//打印日志

System.out.println("[after] The method ends with " + result);

return result;

}

};

/**

* loader: 代理对象使用的类加载器。

* interfaces: 指定代理对象的类型. 即代理代理对象中可以有哪些方法.

* h: 当具体调用代理对象的方法时, 应该如何进行响应, 实际上就是调用 InvocationHandler 的 invoke 方法

*/

proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);

return proxy;

}

}

aop\LoggingAspect.java

package com.atguigu.spring.aop;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.annotation.After;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.springframework.stereotype.Component;

/**

* AOP 的 helloWorld

* 1. 加入 jar 包

* com.springsource.net.sf.cglib-2.2.0.jar

* com.springsource.org.aopalliance-1.0.0.jar

* com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

* spring-aspects-4.0.0.RELEASE.jar

*

* 2. 在 Spring 的配置文件中加入 aop 的命名空间。

*

* 3. 基于注解的方式来使用 AOP

* 3.1 在配置文件中配置自动扫描的包: <context:component-scan base-package="com.atguigu.spring.aop"></context:component-scan>

* 3.2 加入使 AspjectJ 注解起作用的配置: <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

* 为匹配的类自动生成动态代理对象.

*

* 4. 编写切面类:

* 4.1 一个一般的 Java 类

* 4.2 在其中添加要额外实现的功能.

*

* 5. 配置切面

* 5.1 切面必须是 IOC 中的 bean: 实际添加了 @Component 注解

* 5.2 声明是一个切面: 添加 @Aspect

* 5.3 声明通知: 即额外加入功能对应的方法.

* 5.3.1 前置通知: @Before("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(int, int))")

* @Before 表示在目标方法执行之前执行 @Before 标记的方法的方法体.

* @Before 里面的是切入点表达式:

*

* 6. 在通知中访问连接细节: 可以在通知方法中添加 JoinPoint 类型的参数, 从中可以访问到方法的签名和方法的参数.

*

* 7. @After 表示后置通知: 在方法执行之后执行的代码.

*/

//通过添加 @Aspect 注解声明一个 bean 是一个切面!

@Aspect

@Component

@Aspect

@Component

public class LoggingAspect {

@Before

@Before("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(int, int))")

public void beforeMethod(JoinPoint joinPoint){

String methodName = joinPoint.getSignature().getName();

Object [] args = joinPoint.getArgs();

System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));

}

@After

@After("execution(* com.atguigu.spring.aop.*.*(..))")

public void afterMethod(JoinPoint joinPoint){

String methodName = joinPoint.getSignature().getName();

System.out.println("The method " + methodName + " ends");

}

}

aop\Main.java

package com.atguigu.spring.aop;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

public static void main(String[] args) {

//      ArithmeticCalculator arithmeticCalculator = new ArithmeticCalculatorImpl();

//

//      arithmeticCalculator =

//              new ArithmeticCalculatorLoggingProxy(arithmeticCalculator).getLoggingProxy();

//

//      int result = arithmeticCalculator.add(11, 12);

//      System.out.println("result:" + result);

//

//      result = arithmeticCalculator.div(21, 3);

//      System.out.println("result:" + result);

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-aop.xml");

ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator) ctx.getBean("arithmeticCalculator");

System.out.println(arithmeticCalculator.getClass().getName());

int result = arithmeticCalculator.add(11, 12);

System.out.println("result:" + result);

result = arithmeticCalculator.div(21, 3);

System.out.println("result:" + result);

}

}

helloworld\HelloWorld.java

package com.atguigu.spring.helloworld;

public class HelloWorld {

//字段

private String user;

public HelloWorld() {

System.out.println("HelloWorld‘s constructor...");

}

//JavaBean 使用 setter 和 getter 来定义属性

public void setUserName(String user) {

System.out.println("setUserName:" + user);

this.user = user;

}

public void hello(){

System.out.println("Hello:" + user);

}

public void init(){

System.out.println("init method...");

}

public void destroy(){

System.out.println("destroy method...");

}

}

helloworld\Main.java

package com.atguigu.spring.helloworld;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

public static void main(String[] args) {

//1. 创建 IOC 容器

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

//2. 从 IOC 容器中获取 bean 实例

HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");

//3. 调用 bean 的方法

helloWorld.hello();

HelloWorld helloWorld2 = (HelloWorld) ctx.getBean("helloWorld");

System.out.println(helloWorld == helloWorld2);

//4. 关闭容器

ctx.close();

}

}

ref\Main.java

package com.atguigu.spring.ref;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

public static void main(String[] args) {

//1. 创建 IOC 容器

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-annotation.xml");

UserAction userAction = (UserAction) ctx.getBean("userAction");

userAction.execute();

}

}

ref\UserAction.java

package com.atguigu.spring.ref;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

@Controller

@Controller

public class UserAction {

private UserService userService;

@Autowired

@Autowired

public void setUserService(UserService userService) {

this.userService = userService;

}

public void execute(){

System.out.println("execute...");

userService.addNew();

}

}

ref\UserDao.java

package com.atguigu.spring.ref;

import org.springframework.stereotype.Repository;

@Repository

@Repository

public class UserDao {

public void save(){

System.out.println("UserDao‘s save...");

}

}

ref\UserService.java

package com.atguigu.spring.ref;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

@Service

@Service

public class UserService {

@Autowired

private UserDao userDao;

public void setUserDao(UserDao userDao) {

this.userDao = userDao;

}

public void addNew(){

System.out.println("addNew...");

userDao.save();

}

}

spring-3

src\applicationContext-xml.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-4.0.xsd">

<!-- 配置 bean -->

<bean id="arithmeticCalculator"

class="com.atguigu.spring.aop.xml.ArithmeticCalculatorImpl"></bean>

<!-- 配置切面的 bean. -->

<bean id="loggingAspect"

class="com.atguigu.spring.aop.xml.LoggingAspect"></bean>

<bean id="vlidationAspect"

class="com.atguigu.spring.aop.xml.VlidationAspect"></bean>

aop:config

<!-- 配置 AOP -->

<aop:config>

aop:pointcut

<!-- 配置切点表达式 -->

<aop:pointcut expression="execution(* com.atguigu.spring.aop.xml.ArithmeticCalculator.*(int, int))"

id="pointcut"/>

aop:aspect

<!-- 配置切面及通知 -->

<aop:aspect ref="loggingAspect" order="2">

<aop:before method="beforeMethod" pointcut-ref="pointcut"/>

<aop:after method="afterMethod" pointcut-ref="pointcut"/>

<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/>

<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>

<!--

<aop:around method="aroundMethod" pointcut-ref="pointcut"/>

-->

</aop:aspect>

<aop:aspect ref="vlidationAspect" order="1">

<aop:before method="validateArgs" pointcut-ref="pointcut"/>

</aop:aspect>

</aop:config>

</beans>

src\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/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd

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-4.0.xsd">

<!-- 配置自动扫描的包 -->

<context:component-scan base-package="com.atguigu.spring.aop"></context:component-scan>

aop:aspectj-autoproxy

<!-- 配置自动为匹配 aspectJ 注解的 Java 类生成代理对象 -->

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

aop\ArithmeticCalculator.java

package com.atguigu.spring.aop;

public interface ArithmeticCalculator {

int add(int i, int j);

int sub(int i, int j);

int mul(int i, int j);

int div(int i, int j);

}

aop\ArithmeticCalculatorImpl.java

package com.atguigu.spring.aop;

import org.springframework.stereotype.Component;

@Component("arithmeticCalculator")

@Component("arithmeticCalculator")

public class ArithmeticCalculatorImpl implements ArithmeticCalculator {

@Override

public int add(int i, int j) {

int result = i + j;

return result;

}

@Override

public int sub(int i, int j) {

int result = i - j;

return result;

}

@Override

public int mul(int i, int j) {

int result = i * j;

return result;

}

@Override

public int div(int i, int j) {

int result = i / j;

return result;

}

}

aop\LoggingAspect.java

package com.atguigu.spring.aop;

import java.util.Arrays;

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;

import org.springframework.core.annotation.Order;

import org.springframework.stereotype.Component;

/**

* 可以使用 @Order 注解指定切面的优先级, 值越小优先级越高

*/

@Order(2)

@Aspect

@Component

@Order(2)

@Aspect

@Component

public class LoggingAspect {

@Pointcut

/**

* 定义一个方法, 用于声明切入点表达式. 一般地, 该方法中再不需要添入其他的代码.

* 使用 @Pointcut 来声明切入点表达式.

* 后面的其他通知直接使用方法名来引用当前的切入点表达式.

*/

@Pointcut("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))")

public void declareJointPointExpression(){}

@Before

/**

* 在 com.atguigu.spring.aop.ArithmeticCalculator 接口的每一个实现类的每一个方法开始之前执行一段代码

*/

@Before("declareJointPointExpression()")

public void beforeMethod(JoinPoint joinPoint){

String methodName = joinPoint.getSignature().getName();

Object [] args = joinPoint.getArgs();

System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));

}

@After

/**

* 在方法执行之后执行的代码. 无论该方法是否出现异常

*/

@After("declareJointPointExpression()")

public void afterMethod(JoinPoint joinPoint){

String methodName = joinPoint.getSignature().getName();

System.out.println("The method " + methodName + " ends");

}

@AfterReturning

/**

* 在方法法正常结束受执行的代码

* 返回通知是可以访问到方法的返回值的!

*/

@AfterReturning(value="declareJointPointExpression()",

returning="result")

public void afterReturning(JoinPoint joinPoint, Object result){

String methodName = joinPoint.getSignature().getName();

System.out.println("The method " + methodName + " ends with " + result);

}

@AfterThrowing

/**

* 在目标方法出现异常时会执行的代码.

* 可以访问到异常对象; 且可以指定在出现特定异常时在执行通知代码

*/

@AfterThrowing(value="declareJointPointExpression()",

throwing="e")

public void afterThrowing(JoinPoint joinPoint, Exception e){

String methodName = joinPoint.getSignature().getName();

System.out.println("The method " + methodName + " occurs excetion:" + e);

}

@Around

/**

* 环绕通知需要携带 ProceedingJoinPoint 类型的参数.

* 环绕通知类似于动态代理的全过程: ProceedingJoinPoint 类型的参数可以决定是否执行目标方法.

* 且环绕通知必须有返回值, 返回值即为目标方法的返回值

*/

/*

@Around("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))")

public Object aroundMethod(ProceedingJoinPoint pjd){

Object result = null;

String methodName = pjd.getSignature().getName();

try {

//前置通知

System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs()));

//执行目标方法

result = pjd.proceed();

//返回通知

System.out.println("The method " + methodName + " ends with " + result);

} catch (Throwable e) {

//异常通知

System.out.println("The method " + methodName + " occurs exception:" + e);

throw new RuntimeException(e);

}

//后置通知

System.out.println("The method " + methodName + " ends");

return result;

}

*/

}

aop\Main.java

package com.atguigu.spring.aop;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

public static void main(String[] args) {

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator) ctx.getBean("arithmeticCalculator");

System.out.println(arithmeticCalculator.getClass().getName());

int result = arithmeticCalculator.add(1, 2);

System.out.println("result:" + result);

result = arithmeticCalculator.div(1000, 10);

System.out.println("result:" + result);

}

}

aop\VlidationAspect.java

package com.atguigu.spring.aop;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.springframework.core.annotation.Order;

import org.springframework.stereotype.Component;

@Order(1)

@Aspect

@Component

@Order(1)

@Aspect

@Component

public class VlidationAspect {

@Before

@Before("com.atguigu.spring.aop.LoggingAspect.declareJointPointExpression()")

public void validateArgs(JoinPoint joinPoint){

System.out.println("-->validate:" + Arrays.asList(joinPoint.getArgs()));

}

}

aop\xml\ArithmeticCalculator.java

package com.atguigu.spring.aop.xml;

public interface ArithmeticCalculator {

int add(int i, int j);

int sub(int i, int j);

int mul(int i, int j);

int div(int i, int j);

}

aop\xml\ArithmeticCalculatorImpl.java

package com.atguigu.spring.aop.xml;

public class ArithmeticCalculatorImpl implements ArithmeticCalculator {

@Override

public int add(int i, int j) {

int result = i + j;

return result;

}

@Override

public int sub(int i, int j) {

int result = i - j;

return result;

}

@Override

public int mul(int i, int j) {

int result = i * j;

return result;

}

@Override

public int div(int i, int j) {

int result = i / j;

return result;

}

}

aop\xml\LoggingAspect.java

package com.atguigu.spring.aop.xml;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.Around;

public class LoggingAspect {

public void beforeMethod(JoinPoint joinPoint){

String methodName = joinPoint.getSignature().getName();

Object [] args = joinPoint.getArgs();

System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));

}

public void afterMethod(JoinPoint joinPoint){

String methodName = joinPoint.getSignature().getName();

System.out.println("The method " + methodName + " ends");

}

public void afterReturning(JoinPoint joinPoint, Object result){

String methodName = joinPoint.getSignature().getName();

System.out.println("The method " + methodName + " ends with " + result);

}

public void afterThrowing(JoinPoint joinPoint, Exception e){

String methodName = joinPoint.getSignature().getName();

System.out.println("The method " + methodName + " occurs excetion:" + e);

}

@Around("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))")

public Object aroundMethod(ProceedingJoinPoint pjd){

Object result = null;

String methodName = pjd.getSignature().getName();

try {

//前置通知

System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs()));

//执行目标方法

result = pjd.proceed();

//返回通知

System.out.println("The method " + methodName + " ends with " + result);

} catch (Throwable e) {

//异常通知

System.out.println("The method " + methodName + " occurs exception:" + e);

throw new RuntimeException(e);

}

//后置通知

System.out.println("The method " + methodName + " ends");

return result;

}

}

aop\xml\Main.java

package com.atguigu.spring.aop.xml;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

public static void main(String[] args) {

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-xml.xml");

ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator) ctx.getBean("arithmeticCalculator");

System.out.println(arithmeticCalculator.getClass().getName());

int result = arithmeticCalculator.add(1, 2);

System.out.println("result:" + result);

result = arithmeticCalculator.div(1000, 0);

System.out.println("result:" + result);

}

}

aop\xml\VlidationAspect.java

package com.atguigu.spring.aop.xml;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;

public class VlidationAspect {

public void validateArgs(JoinPoint joinPoint){

System.out.println("-->validate:" + Arrays.asList(joinPoint.getArgs()));

}

}

spring-4

src\applicationContext-tx-xml.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:tx="http://www.springframework.org/schema/tx"

xmlns:aop="http://www.springframework.org/schema/aop"

xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

<context:component-scan base-package="com.atguigu.spring"></context:component-scan>

<!-- 导入资源文件 -->

<context:property-placeholder location="classpath:db.properties"/>

<!-- 配置 C3P0 数据源 -->

<bean id="dataSource"

class="com.mchange.v2.c3p0.ComboPooledDataSource">

<property name="user" value="${jdbc.user}"></property>

<property name="password" value="${jdbc.password}"></property>

<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>

<property name="driverClass" value="${jdbc.driverClass}"></property>

<property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>

<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>

</bean>

<!-- 配置 Spirng 的 JdbcTemplate -->

<bean id="jdbcTemplate"

class="org.springframework.jdbc.core.JdbcTemplate">

<property name="dataSource" ref="dataSource"></property>

</bean>

<!-- 配置 bean -->

<bean id="bookShopDao" class="com.atguigu.spring.tx.xml.BookShopDaoImpl">

<property name="jdbcTemplate" ref="jdbcTemplate"></property>

</bean>

<bean id="bookShopService" class="com.atguigu.spring.tx.xml.service.impl.BookShopServiceImpl">

<property name="bookShopDao" ref="bookShopDao"></property>

</bean>

<bean id="cashier" class="com.atguigu.spring.tx.xml.service.impl.CashierImpl">

<property name="bookShopService" ref="bookShopService"></property>

</bean>

<!-- 1. 配置事务管理器 -->

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dataSource"></property>

</bean>

<!-- 2. 配置事务属性 -->

<tx:advice id="txAdvice" transaction-manager="transactionManager">

<tx:attributes>

<!-- 根据方法名指定事务的属性 -->

<tx:method name="purchase" propagation="REQUIRES_NEW"/>

<tx:method name="get*" read-only="true"/>

<tx:method name="find*" read-only="true"/>

<tx:method name="*"/>

</tx:attributes>

</tx:advice>

<!-- 3. 配置事务切入点, 以及把事务切入点和事务属性关联起来 -->

<aop:config>

<aop:pointcut expression="execution(* com.atguigu.spring.tx.xml.service.*.*(..))"

id="txPointCut"/>

<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>

</aop:config>

</beans>

src\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:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

<context:component-scan base-package="com.atguigu.spring"></context:component-scan>

<!-- 导入资源文件 -->

<context:property-placeholder location="classpath:db.properties"/>

<!-- 配置 C3P0 数据源 -->

<bean id="dataSource"

class="com.mchange.v2.c3p0.ComboPooledDataSource">

<property name="user" value="${jdbc.user}"></property>

<property name="password" value="${jdbc.password}"></property>

<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>

<property name="driverClass" value="${jdbc.driverClass}"></property>

<property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>

<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>

</bean>

<!-- 配置 Spirng 的 JdbcTemplate -->

<bean id="jdbcTemplate"

class="org.springframework.jdbc.core.JdbcTemplate">

<property name="dataSource" ref="dataSource"></property>

</bean>

<!-- 配置 NamedParameterJdbcTemplate, 该对象可以使用具名参数, 其没有无参数的构造器, 所以必须为其构造器指定参数 -->

<bean id="namedParameterJdbcTemplate"

class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">

<constructor-arg ref="dataSource"></constructor-arg>

</bean>

<!-- 配置事务管理器 -->

<bean id="transactionManager"

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dataSource"></property>

</bean>

<!-- 启用事务注解 -->

<tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

jdbc\Department.java

package com.atguigu.spring.jdbc;

public class Department {

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 "Department [id=" + id + ", name=" + name + "]";

}

}

jdbc\DepartmentDao.java

package com.atguigu.spring.jdbc;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.jdbc.core.BeanPropertyRowMapper;

import org.springframework.jdbc.core.RowMapper;

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

import org.springframework.stereotype.Repository;

/**

* 不推荐使用 JdbcDaoSupport, 而推荐直接使用 JdbcTempate 作为 Dao 类的成员变量

*/

@Repository

public class DepartmentDao extends JdbcDaoSupport{

@Autowired

public void setDataSource2(DataSource dataSource){

setDataSource(dataSource);

}

public Department get(Integer id){

String sql = "SELECT id, dept_name name FROM departments WHERE id = ?";

RowMapper<Department> rowMapper = new BeanPropertyRowMapper<>(Department.class);

return getJdbcTemplate().queryForObject(sql, rowMapper, id);

}

}

jdbc\Employee.java

package com.atguigu.spring.jdbc;

public class Employee {

private Integer id;

private String lastName;

private String email;

private Integer dpetId;

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

public String getLastName() {

return lastName;

}

public void setLastName(String lastName) {

this.lastName = lastName;

}

public String getEmail() {

return email;

}

public void setEmail(String email) {

this.email = email;

}

public Integer getDpetId() {

return dpetId;

}

public void setDpetId(Integer dpetId) {

this.dpetId = dpetId;

}

@Override

public String toString() {

return "Employee [id=" + id + ", lastName=" + lastName + ", email="

+ email + ", dpetId=" + dpetId + "]";

}

}

jdbc\EmployeeDao.java

package com.atguigu.spring.jdbc;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.jdbc.core.BeanPropertyRowMapper;

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.jdbc.core.RowMapper;

import org.springframework.stereotype.Repository;

@Repository

public class EmployeeDao {

@Autowired

private JdbcTemplate jdbcTemplate;

public Employee get(Integer id){

String sql = "SELECT id, last_name lastName, email FROM employees WHERE id = ?";

RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<>(Employee.class);

Employee employee = jdbcTemplate.queryForObject(sql, rowMapper, id);

return employee;

}

}

jdbc\JDBCTest.java

package com.atguigu.spring.jdbc;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import javax.sql.DataSource;

import org.junit.Test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import org.springframework.jdbc.core.BeanPropertyRowMapper;

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.jdbc.core.RowMapper;

import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;

import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import org.springframework.jdbc.core.namedparam.SqlParameterSource;

public class JDBCTest {

private ApplicationContext ctx = null;

private JdbcTemplate jdbcTemplate;

private EmployeeDao employeeDao;

private DepartmentDao departmentDao;

private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

{

ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate");

employeeDao = ctx.getBean(EmployeeDao.class);

departmentDao = ctx.getBean(DepartmentDao.class);

namedParameterJdbcTemplate = ctx.getBean(NamedParameterJdbcTemplate.class);

}

/**

* 使用具名参数时, 可以使用 update(String sql, SqlParameterSource paramSource) 方法进行更新操作

* 1. SQL 语句中的参数名和类的属性一致!

* 2. 使用 SqlParameterSource 的 BeanPropertySqlParameterSource 实现类作为参数.

*/

@Test

public void testNamedParameterJdbcTemplate2(){

String sql = "INSERT INTO employees(last_name, email, dept_id) "

+ "VALUES(:lastName,:email,:dpetId)";

Employee employee = new Employee();

employee.setLastName("XYZ");

employee.setEmail("[email protected]");

employee.setDpetId(3);

SqlParameterSource paramSource = new BeanPropertySqlParameterSource(employee);

namedParameterJdbcTemplate.update(sql, paramSource);

}

/**

* 可以为参数起名字.

* 1. 好处: 若有多个参数, 则不用再去对应位置, 直接对应参数名, 便于维护

* 2. 缺点: 较为麻烦.

*/

@Test

public void testNamedParameterJdbcTemplate(){

String sql = "INSERT INTO employees(last_name, email, dept_id) VALUES(:ln,:email,:deptid)";

Map<String, Object> paramMap = new HashMap<>();

paramMap.put("ln", "FF");

paramMap.put("email", "[email protected]");

paramMap.put("deptid", 2);

namedParameterJdbcTemplate.update(sql, paramMap);

}

@Test

public void testDepartmentDao(){

System.out.println(departmentDao.get(1));

}

@Test

public void testEmployeeDao(){

System.out.println(employeeDao.get(1));

}

/**

* 获取单个列的值, 或做统计查询

* 使用 queryForObject(String sql, Class<Long> requiredType)

*/

@Test

public void testQueryForObject2(){

String sql = "SELECT count(id) FROM employees";

long count = jdbcTemplate.queryForObject(sql, Long.class);

System.out.println(count);

}

/**

* 查到实体类的集合

* 注意调用的不是 queryForList 方法

*/

@Test

public void testQueryForList(){

String sql = "SELECT id, last_name lastName, email FROM employees WHERE id > ?";

RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<>(Employee.class);

List<Employee> employees = jdbcTemplate.query(sql, rowMapper,5);

System.out.println(employees);

}

/**

* 从数据库中获取一条记录, 实际得到对应的一个对象

* 注意不是调用 queryForObject(String sql, Class<Employee> requiredType, Object... args) 方法!

* 而需要调用 queryForObject(String sql, RowMapper<Employee> rowMapper, Object... args)

* 1. 其中的 RowMapper 指定如何去映射结果集的行, 常用的实现类为 BeanPropertyRowMapper

* 2. 使用 SQL 中列的别名完成列名和类的属性名的映射. 例如 last_name lastName

* 3. 不支持级联属性. JdbcTemplate 到底是一个 JDBC 的小工具, 而不是 ORM 框架

*/

@Test

public void testQueryForObject(){

String sql = "SELECT id, last_name lastName, email, dept_id as \"department.id\" FROM employees WHERE id = ?";

RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<>(Employee.class);

Employee employee = jdbcTemplate.queryForObject(sql, rowMapper, 1);

System.out.println(employee);

}

/**

* 执行批量更新: 批量的 INSERT, UPDATE, DELETE

* 最后一个参数是 Object[] 的 List 类型: 因为修改一条记录需要一个 Object 的数组, 那么多条不就需要多个 Object 的数组吗

*/

@Test

public void testBatchUpdate(){

String sql = "INSERT INTO employees(last_name, email, dept_id) VALUES(?,?,?)";

List<Object[]> batchArgs = new ArrayList<>();

batchArgs.add(new Object[]{"AA", "[email protected]", 1});

batchArgs.add(new Object[]{"BB", "[email protected]", 2});

batchArgs.add(new Object[]{"CC", "[email protected]", 3});

batchArgs.add(new Object[]{"DD", "[email protected]", 3});

batchArgs.add(new Object[]{"EE", "[email protected]", 2});

jdbcTemplate.batchUpdate(sql, batchArgs);

}

/**

* 执行 INSERT, UPDATE, DELETE

*/

@Test

public void testUpdate(){

String sql = "UPDATE employees SET last_name = ? WHERE id = ?";

jdbcTemplate.update(sql, "Jack", 5);

}

@Test

public void testDataSource() throws SQLException {

DataSource dataSource = ctx.getBean(DataSource.class);

System.out.println(dataSource.getConnection());

}

}

tx\BookShopDao.java

package com.atguigu.spring.tx;

public interface BookShopDao {

//根据书号获取书的单价

public int findBookPriceByIsbn(String isbn);

//更新数的库存. 使书号对应的库存 - 1

public void updateBookStock(String isbn);

//更新用户的账户余额: 使 username 的 balance - price

public void updateUserAccount(String username, int price);

}

tx\BookShopDaoImpl.java

package com.atguigu.spring.tx;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.stereotype.Repository;

@Repository("bookShopDao")

public class BookShopDaoImpl implements BookShopDao {

@Autowired

private JdbcTemplate jdbcTemplate;

@Override

public int findBookPriceByIsbn(String isbn) {

String sql = "SELECT price FROM book WHERE isbn = ?";

return jdbcTemplate.queryForObject(sql, Integer.class, isbn);

}

@Override

public void updateBookStock(String isbn) {

//检查书的库存是否足够, 若不够, 则抛出异常

String sql2 = "SELECT stock FROM book_stock WHERE isbn = ?";

int stock = jdbcTemplate.queryForObject(sql2, Integer.class, isbn);

if(stock == 0){

throw new BookStockException("库存不足!");

}

String sql = "UPDATE book_stock SET stock = stock -1 WHERE isbn = ?";

jdbcTemplate.update(sql, isbn);

}

@Override

public void updateUserAccount(String username, int price) {

//验证余额是否足够, 若不足, 则抛出异常

String sql2 = "SELECT balance FROM account WHERE username = ?";

int balance = jdbcTemplate.queryForObject(sql2, Integer.class, username);

if(balance < price){

throw new UserAccountException("余额不足!");

}

String sql = "UPDATE account SET balance = balance - ? WHERE username = ?";

jdbcTemplate.update(sql, price, username);

}

}

tx\BookShopService.java

package com.atguigu.spring.tx;

public interface BookShopService {

public void purchase(String username, String isbn);

}

tx\BookShopServiceImpl.java

package com.atguigu.spring.tx;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Isolation;

import org.springframework.transaction.annotation.Propagation;

import org.springframework.transaction.annotation.Transactional;

@Service("bookShopService")

public class BookShopServiceImpl implements BookShopService {

@Autowired

private BookShopDao bookShopDao;

//添加事务注解

//1.使用 propagation 指定事务的传播行为, 即当前的事务方法被另外一个事务方法调用时

//如何使用事务, 默认取值为 REQUIRED, 即使用调用方法的事务

//REQUIRES_NEW: 事务自己的事务, 调用的事务方法的事务被挂起.

//2.使用 isolation 指定事务的隔离级别, 最常用的取值为 READ_COMMITTED

//3.默认情况下 Spring 的声明式事务对所有的运行时异常进行回滚. 也可以通过对应的

//属性进行设置. 通常情况下去默认值即可.

//4.使用 readOnly 指定事务是否为只读. 表示这个事务只读取数据但不更新数据,

//这样可以帮助数据库引擎优化事务. 若真的事一个只读取数据库值的方法, 应设置 readOnly=true

//5.使用 timeout 指定强制回滚之前事务可以占用的时间.

//  @Transactional(propagation=Propagation.REQUIRES_NEW,

//          isolation=Isolation.READ_COMMITTED,

//          noRollbackFor={UserAccountException.class})

@Transactional(propagation=Propagation.REQUIRES_NEW,

isolation=Isolation.READ_COMMITTED,

readOnly=false,

timeout=3)

@Override

public void purchase(String username, String isbn) {

try {

Thread.sleep(5000);

} catch (InterruptedException e) {}

//1. 获取书的单价

int price = bookShopDao.findBookPriceByIsbn(isbn);

//2. 更新数的库存

bookShopDao.updateBookStock(isbn);

//3. 更新用户余额

bookShopDao.updateUserAccount(username, price);

}

}

tx\BookStockException.java

package com.atguigu.spring.tx;

public class BookStockException extends RuntimeException{

/**

*

*/

private static final long serialVersionUID = 1L;

public BookStockException() {

super();

// TODO Auto-generated constructor stub

}

public BookStockException(String message, Throwable cause,

boolean enableSuppression, boolean writableStackTrace) {

super(message, cause, enableSuppression, writableStackTrace);

// TODO Auto-generated constructor stub

}

public BookStockException(String message, Throwable cause) {

super(message, cause);

// TODO Auto-generated constructor stub

}

public BookStockException(String message) {

super(message);

// TODO Auto-generated constructor stub

}

public BookStockException(Throwable cause) {

super(cause);

// TODO Auto-generated constructor stub

}

}

tx\Cashier.java

package com.atguigu.spring.tx;

import java.util.List;

public interface Cashier {

public void checkout(String username, List<String> isbns);

}

tx\CashierImpl.java

package com.atguigu.spring.tx;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

@Service("cashier")

public class CashierImpl implements Cashier {

@Autowired

private BookShopService bookShopService;

@Transactional

@Override

public void checkout(String username, List<String> isbns) {

for(String isbn: isbns){

bookShopService.purchase(username, isbn);

}

}

}

tx\SpringTransactionTest.java

package com.atguigu.spring.tx;

import static org.junit.Assert.*;

import java.util.Arrays;

import org.junit.Test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTransactionTest {

private ApplicationContext ctx = null;

private BookShopDao bookShopDao = null;

private BookShopService bookShopService = null;

private Cashier cashier = null;

{

ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

bookShopDao = ctx.getBean(BookShopDao.class);

bookShopService = ctx.getBean(BookShopService.class);

cashier = ctx.getBean(Cashier.class);

}

@Test

public void testTransactionlPropagation(){

cashier.checkout("AA", Arrays.asList("1001", "1002"));

}

@Test

public void testBookShopService(){

bookShopService.purchase("AA", "1001");

}

@Test

public void testBookShopDaoUpdateUserAccount(){

bookShopDao.updateUserAccount("AA", 200);

}

@Test

public void testBookShopDaoUpdateBookStock(){

bookShopDao.updateBookStock("1001");

}

@Test

public void testBookShopDaoFindPriceByIsbn() {

System.out.println(bookShopDao.findBookPriceByIsbn("1001"));

}

}

tx\UserAccountException.java

package com.atguigu.spring.tx;

public class UserAccountException extends RuntimeException{

/**

*

*/

private static final long serialVersionUID = 1L;

public UserAccountException() {

super();

// TODO Auto-generated constructor stub

}

public UserAccountException(String message, Throwable cause,

boolean enableSuppression, boolean writableStackTrace) {

super(message, cause, enableSuppression, writableStackTrace);

// TODO Auto-generated constructor stub

}

public UserAccountException(String message, Throwable cause) {

super(message, cause);

// TODO Auto-generated constructor stub

}

public UserAccountException(String message) {

super(message);

// TODO Auto-generated constructor stub

}

public UserAccountException(Throwable cause) {

super(cause);

// TODO Auto-generated constructor stub

}

}

tx\xml\BookShopDao.java

package com.atguigu.spring.tx.xml;

public interface BookShopDao {

//根据书号获取书的单价

public int findBookPriceByIsbn(String isbn);

//更新数的库存. 使书号对应的库存 - 1

public void updateBookStock(String isbn);

//更新用户的账户余额: 使 username 的 balance - price

public void updateUserAccount(String username, int price);

}

tx\xml\BookShopDaoImpl.java

package com.atguigu.spring.tx.xml;

import org.springframework.jdbc.core.JdbcTemplate;

public class BookShopDaoImpl implements BookShopDao {

private JdbcTemplate jdbcTemplate;

public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {

this.jdbcTemplate = jdbcTemplate;

}

@Override

public int findBookPriceByIsbn(String isbn) {

String sql = "SELECT price FROM book WHERE isbn = ?";

return jdbcTemplate.queryForObject(sql, Integer.class, isbn);

}

@Override

public void updateBookStock(String isbn) {

//检查书的库存是否足够, 若不够, 则抛出异常

String sql2 = "SELECT stock FROM book_stock WHERE isbn = ?";

int stock = jdbcTemplate.queryForObject(sql2, Integer.class, isbn);

if(stock == 0){

throw new BookStockException("库存不足!");

}

String sql = "UPDATE book_stock SET stock = stock -1 WHERE isbn = ?";

jdbcTemplate.update(sql, isbn);

}

@Override

public void updateUserAccount(String username, int price) {

//验证余额是否足够, 若不足, 则抛出异常

String sql2 = "SELECT balance FROM account WHERE username = ?";

int balance = jdbcTemplate.queryForObject(sql2, Integer.class, username);

if(balance < price){

throw new UserAccountException("余额不足!");

}

String sql = "UPDATE account SET balance = balance - ? WHERE username = ?";

jdbcTemplate.update(sql, price, username);

}

}

tx\xml\BookStockException.java

package com.atguigu.spring.tx.xml;

public class BookStockException extends RuntimeException{

/**

*

*/

private static final long serialVersionUID = 1L;

public BookStockException() {

super();

// TODO Auto-generated constructor stub

}

public BookStockException(String message, Throwable cause,

boolean enableSuppression, boolean writableStackTrace) {

super(message, cause, enableSuppression, writableStackTrace);

// TODO Auto-generated constructor stub

}

public BookStockException(String message, Throwable cause) {

super(message, cause);

// TODO Auto-generated constructor stub

}

public BookStockException(String message) {

super(message);

// TODO Auto-generated constructor stub

}

public BookStockException(Throwable cause) {

super(cause);

// TODO Auto-generated constructor stub

}

}

tx\xml\SpringTransactionTest.java

package com.atguigu.spring.tx.xml;

import java.util.Arrays;

import org.junit.Test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.atguigu.spring.tx.xml.service.BookShopService;

import com.atguigu.spring.tx.xml.service.Cashier;

public class SpringTransactionTest {

private ApplicationContext ctx = null;

private BookShopDao bookShopDao = null;

private BookShopService bookShopService = null;

private Cashier cashier = null;

{

ctx = new ClassPathXmlApplicationContext("applicationContext-tx-xml.xml");

bookShopDao = ctx.getBean(BookShopDao.class);

bookShopService = ctx.getBean(BookShopService.class);

cashier = ctx.getBean(Cashier.class);

}

@Test

public void testTransactionlPropagation(){

cashier.checkout("AA", Arrays.asList("1001", "1002"));

}

@Test

public void testBookShopService(){

bookShopService.purchase("AA", "1001");

}

}

tx\xml\UserAccountException.java

package com.atguigu.spring.tx.xml;

public class UserAccountException extends RuntimeException{

/**

*

*/

private static final long serialVersionUID = 1L;

public UserAccountException() {

super();

// TODO Auto-generated constructor stub

}

public UserAccountException(String message, Throwable cause,

boolean enableSuppression, boolean writableStackTrace) {

super(message, cause, enableSuppression, writableStackTrace);

// TODO Auto-generated constructor stub

}

public UserAccountException(String message, Throwable cause) {

super(message, cause);

// TODO Auto-generated constructor stub

}

public UserAccountException(String message) {

super(message);

// TODO Auto-generated constructor stub

}

public UserAccountException(Throwable cause) {

super(cause);

// TODO Auto-generated constructor stub

}

}

tx\xml\service\BookShopService.java

package com.atguigu.spring.tx.xml.service;

public interface BookShopService {

public void purchase(String username, String isbn);

}

tx\xml\service\Cashier.java

package com.atguigu.spring.tx.xml.service;

import java.util.List;

public interface Cashier {

public void checkout(String username, List<String> isbns);

}

tx\xml\service\impl\BookShopServiceImpl.java

package com.atguigu.spring.tx.xml.service.impl;

import com.atguigu.spring.tx.xml.BookShopDao;

import com.atguigu.spring.tx.xml.service.BookShopService;

public class BookShopServiceImpl implements BookShopService {

private BookShopDao bookShopDao;

public void setBookShopDao(BookShopDao bookShopDao) {

this.bookShopDao = bookShopDao;

}

@Override

public void purchase(String username, String isbn) {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {}

//1. 获取书的单价

int price = bookShopDao.findBookPriceByIsbn(isbn);

//2. 更新数的库存

bookShopDao.updateBookStock(isbn);

//3. 更新用户余额

bookShopDao.updateUserAccount(username, price);

}

}

tx\xml\service\impl\CashierImpl.java

package com.atguigu.spring.tx.xml.service.impl;

import java.util.List;

import com.atguigu.spring.tx.xml.service.BookShopService;

import com.atguigu.spring.tx.xml.service.Cashier;

public class CashierImpl implements Cashier {

private BookShopService bookShopService;

public void setBookShopService(BookShopService bookShopService) {

this.bookShopService = bookShopService;

}

@Override

public void checkout(String username, List<String> isbns) {

for(String isbn: isbns){

bookShopService.purchase(username, isbn);

}

}

}

End

时间: 2024-10-17 07:03:17

Note_JavaWeb_Spring_尚硅谷的相关文章

尚硅谷Java视频_jQuery 视频教程

更多Java培训.Java视频教程学习资料,请登录尚硅谷网站下载:www.atguigu.com jQuery是优秀的JavaScript框架,能使用户能更方便地处理HTML documents.events.实现动画效果,并且方便地为网站提供Ajax交互.在世界前10000个访问最多的网站中,有超过 55 6在使用jQuery. 本Java视频教程循序渐进地对jQuery的各种选择器.函数和方法调用进行了详细的讲授,更配备了大量的实例. [视频简介] jQuery 是继 Prototype 之

java学习笔记-尚硅谷0918班高宏*:康师傅,给力,太给力了

不知不觉来尚硅谷java培训已经一个月了,这一个月就这么悄悄地溜走了,无声无息,没给一点挽留的余地,只留下我们在这里感叹:时间都去哪了.就好像只有在写总结的时候才恍然明白:原来我们已经学习了一个多月了.这个月是忙碌的一个月,比上班还要忙:这个月是充实的一个月,比堕落时玩游戏还感觉充实:这个月更是收获的一个月,比上学时候感觉学的还要多,还要深.        1.教学方面 教学方面必须要说康师傅了,给力,太给力了,问的问题总是讲的很透彻,很深入,课堂气氛也搞得很好,经常性习惯性的来几个段子让我们捧

java学习笔记-0918班亓东*:尚硅谷班级的学习气氛浓厚

转眼来北京java培训一个月过去,在这一个月里我认识了很多老师和同学,让我有种重新回到学生时代上学时感觉,这的学习气氛很好,每个同学都很用功的学习,有些基础好的同学也很愿意帮助别人,同学之间的相互关心,相互帮助,解决了很多学习上的问题,说起来还要感谢我的同桌,没有他的帮助我想我也会学的很吃力,每次遇到问题他都能及时帮同学解决,同学之间的彼此帮助,让班级的学习气氛更加浓厚,营造一个良好的学习氛围,对于将来的学习会大有帮助,好的学习氛围是大家共同努力的成果. 在尚硅谷java培训每个阶段都会有阶段性

java学习笔记-尚硅谷0918班刘*:我和宋老师建立了亲密无间的基友关系

时光冉冉,岁月如歌,时光如酒,转眼间我就已经步入了人生的第24个年头选择在北京尚硅谷java培训机构来学校.亦或时,我也会在寂寞无人的夜晚,冰冷孤寂的房间,点燃一根香烟,在烟雾袅袅中,深深的问自己,你,有考虑过自己的人生么!!!!亦或时,躺在床上辗转难眠之后,默默的对自己说,你!不能再这么下去了!!!! 是的,我已经二十四岁了,二十四岁的年纪,当周围邻居的小孩开始叫你叔叔的时候,你有木有感觉到一种~~~啊!人生!还真是失败呀!是的,我不能再这么下去了! 我走过风,走过雨,走过那条无人经过的小巷,

java学习笔记-0918班林代*:感谢尚硅谷给我这样一次改造的机会

时间的长河缓缓流淌,在不经意之间,我已经来到尚硅谷java培训一个多月了.还记得,当初义无反顾的报名参加了尚硅谷北京java培训.带着刚离职的失意以及对未来殷勤的企盼来到了北京,来到了这陌生的都市.陌生的学校. 一个多月了,说长不长,说短不短.在这里我认识了很多爱我的和我敬爱的老师们.同学们.喜欢和他们一起疯狂的玩闹,更享受和他们一起交流学习.我相信,有他们的陪伴我可以斗志昂扬的战胜学习路上的困难.而一个多月的学习也达成了我的目的,梳理自己原来会的知识,让那些知识更稳固的印刻在我的脑海里. 规划

java学习笔记-尚硅谷0918班史营营:学习并不难,难就难在坚持

我来到尚硅谷是被尚硅谷北京java培训的课程体系深深的吸引着,之前有看过佟老师的视频,讲课内容非常丰富,也很风趣,当时就在想如果我能达到佟老师一半的技术水平,那我就相当牛了.当然我现在已经身在尚硅谷了,我的第一位导师是宋老师,很帅气,讲课也很风趣,与很多培训机构不同,尚硅谷的课程设置为每天上下午各三小时,以讲解和宋老师现场编码为主.每上两三天课休息一天,进度安排也很合理.这样毫无水分的课程安排,好处自然是不言而喻的.时间安排紧凑,学生能够跟着老师的思路,模仿着进行操作,体会到真实项目中编程的感觉

java学习笔记-1205班刘*:尚硅谷的环境与氛围绝对是行业之中最顶尖的

时光匆匆,一转眼的时间,一个多月就过去了,回头想想这一个多月以来所得与所失,包括与新同学的接触与相处,与java新知识的理解与领悟,不禁暗自庆幸,这一趟来到这里的学习是非常值得的. 当经历着那些艰辛与困苦之时,我们深深得体会到了面临困境之时,那些痛彻,而经历过之后,这些艰难的岁月确像一笔珍贵的财富将永远存在我们的心中.还记得刚到尚硅谷之时,那些陌生的面孔,陌生的环境,陌生的人群,包括陌生的之时.一切陌生的东西都激起了我心底的厌恶之感,不得不说,我对于陌生的环境还是比较排斥的,但是,当我真正融入到

java学习日记-尚硅谷0722班熊*: 坚持自己的学习方式

在尚硅谷北京java培训机构经过一段时间的紧张学习,在老师的带领下我重温了一边java基础.将我以前没有掌握的io和反射系统的学习了一边.老师以表格的形式将io流的体系画出来,让我更好的整理了脑袋里混乱的流关系.                我很喜欢数据库的学习方式,每天讲完课后可以有大量的练习,通过不同的方式锻炼学习到的内容.如果java基础也能够像数据库一样每个章节讲完后有大量的练习题就好了.毕竟java处了理解还需要很多的练习才能融会贯通,特别是类和类之间的关系使用.         

java学习笔记-0918班马义*,在大雨磅礴中来到尚硅谷

从9月23号在大雨磅礴中来到尚硅谷java培训,已经过去一月有余.五个月的学习路程已走完20%.第一阶段的考试也结束了.北京Java培训和我以往在大学学习的专业有很大不同,这一个多月的学习也让我的文科生思维慢慢转变过来,java很考逻辑思维,如果面向对象的思想有了,学习java就会容易一些.对于编程,我觉得最好的学习方法就是多敲代码,敲到一定程度,代码都是自然而然从指尖流露出来. 通过一个月的学习,我也慢慢找到了自己学习java的方法,每天晚上的自习时间看今天老师的java视频,根据遗忘曲线,如