Spring

1.基本内容

2.操作

2.1快速入门

3.概念

3.1IOC&DI

3.2applicationContext&BeanFactory

4.配置详解

4.1Bean

4.2Spring创建对象的三种方式

4.3 Bean元素进阶

4.3.1 scope属性

4.3.2生命周期属性(了解)

4.4分模块配置

4.5.属性注入

4.6复杂类型注入

5.整合web项目

6.使用注解配置spring

6.1步骤

6.2其他注解说明

7.STS插件

8.springjunit整合测试

9.aop

9.1aop思想

9.2Spring中的aop

9.2.1Spring实现aop原理

9.3aop名词解释

10.aop演示(XML配置)

11.aop演示(注解)

12.Spring整合JDBC

12.1JDBCTemplate

12.2 JDBCTemplate连接数据库

13.Spring与事务

13.1事务的概念

13.2事务环境准备

1.基本内容

spring是为了解决企业应用开发的复杂性而创建的,是一个轻量级的控制反转(IoC)[指的是将对象的创建权反转给Spring,作用是实现了程序的解耦合]和面向切面(AOP)的容器框架。

并不局限于某一层,是对象的容器,帮我们“管理”项目中所有的对象

2.操作

2.1快速入门

1.导包

Log4jspring

2.创建一个对象

public class User {

    private  String name;

    private Integer age;

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public Integer getAge() {

        return age;

    }

    public void setAge(Integer age) {

        this.age = age;

    }

}

3.书写配置注册对象到容器

 

建立xml文件,建议放在src下,文件名建议applicationContext.xml

配置xml文件

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">

<!--User对象交给spring容器管理  ,其中name任意,class为全包名-->

<bean name="user" class="com.jinghang.bean.User"></bean>

</beans>

4.代码测试

 

@Test

public void fun1() {

  //1.创建容器对象,相对于src下的路径

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

  //2.向容器“要”user对象

  User u=(User) ac.getBean("user");

  //3.打印user对象

  System.out.println(u);

}

3.概念

3.1IOC&DI

IOC(控制反转)DI(依赖注入):明确定义组件的接口,独立开发各个组件,然后根据组件的依赖关系组装运行;即将创建及管理对象的权利交给Spring容器。Spring是一个轻型容器(light-weight Container),其核心是Bean工厂(Bean Factory),用以构造我们所需要的M(Model)。能够让相互协作的软件组件保持松散耦合。降低了业务对象替换的复杂性,提高了组件之间的解耦。

 

3.2applicationContext&BeanFactory

BeanFactory 接口

spring原始接口.最底层的接口。针对原始接口的实现类功能较为单一

BeanFactory接口实现类的容器.特点是每次在获得对象时才会创建对象,为了节省内存

ApplicationContext

每次容器启动时就会创建容器中配置的所有对象.并提供更多功能

从类路径下加载配置文件:ClassPathXmlApplicationContext

从硬盘绝对路径下加载配置文件:FileSystemXmlApplicationContext(d:/xxx/yyy/xxx)

4.配置详解

4.1Bean

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">

    <!--User对象交给spring容器管理  ,其中name任意,class为全包名

        class属性:被管理对象的完整类名

        name属性:给被管理的对象起个名字,根据该名称获得对象

            可以重复,可以使用特殊字符

        id属性:name属性一模一样

            名称不可重复,不能使用特殊字符

        结论:尽量使用name属性

    -->

    <bean name="user" class="com.jinghang.bean.User"></bean>

</beans>

4.2Spring创建对象的三种方式

1.空参构造方式(最主要方式)

<!--创建方式1:空参构造创建  -->

 <bean name="user" class="com.jinghang.bean.User"></bean>

//1.创建容器对象,相对于src下的路径

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

2.静态工厂(了解)

public static User createUser() {

        System.out.println("静态工厂创建User");//表示由用户自己创建

        return new User();

    }

<!--创建方式2:静态工厂创建方式  

        调用UserFactorycreateUser方法创建名为user2的对象,放入容器

    -->

    <bean name="user2"

        class="com.jinghang.UserFactory"  //类的全包名

        factory-method="createUser"></bean>     //类的方法

//测试

public void fun2() {

ApplicationContext ac=new ClassPathXmlApplicationContext("com/jinghang/applicationContext.xml");

//2.向容器“要”user对象

User u=(User) ac.getBean("user2");

    }

3.实例工厂(了解)

public  User createUser2() {//不是静态方法

        System.out.println("实例工厂创建User");

        return new User();

    }

    <!--创建方式3:实例工厂创建

            调用UserFactory对象的createUser2方法创建名为user3的对象,放入容器

          -->

    <bean name="user3"

        factory-bean="userFactory"

        factory-method="createUser2"></bean>

    <bean name="userFactory"

        class="com.jinghang.UserFactory" ></bean>

public void fun3() {

        ApplicationContext ac=new ClassPathXmlApplicationContext("com/jinghang/b_create/applicationContext.xml");

        //2.向容器“要”user对象

        User u=(User) ac.getBean("user3");

 

    }

4.3 Bean元素进阶

4.3.1 scope属性

singleton(默认值):单例对象,被标识为单例的对象在spring容器中只会存在一个实例

<bean name="user" class="com.jinghang.bean.User" scope="singleton"></bean>

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

//2.向容器“要”user对象

User u=(User) ac.getBean("user");

User u2=(User) ac.getBean("user");

User u3=(User) ac.getBean("user");

User u4=(User) ac.getBean("user");

//3.打印user对象 会发现只有一个实例

System.out.println(u==u3);

System.out.println(u2==u4);

4.3.2生命周期属性(了解)

配置一个方法作为生命周期初始化方法.spring会在对象创建之后立即调用.

init-method

配置一个方法作为生命周期的销毁方法.spring容器在关闭并销毁所有容器中的对象之前调用.

destory-method

<bean name="user" class="com.jinghang.bean.User" scope="singleton" init-method="init" destroy-method="destroy"></bean>

1

//并在User中实现此方法

public void init() {

        System.out.println("初始化");

    }

 

    public void destroy() {

        System.out.println("销毁");

    }

4.4分模块配置

主配置文件引入其他配置文件

 

//在主配置文件中做如下配置

<import resource="com/jinghang/applicationContext.xml"/>

4.5.属性注入

属于配置方法

 

set方法注入(重要)(前提是set注入之前该对象提供setter方法)

<bean name="user" class="com.jinghang.bean.User" >

    <!--值类型注入:为User对象中名为name的属性注入tom作为值-->

    <property name="name" value="tom"></property>

    <property name="age" value="18"></property>

    <!--引用类型注入:为car属性注入下方配置的car对象   caruser中一个对象-->

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

  </bean>

  <!--car对象配置到容器中 -->

  <bean name="car" class="com.jinghang.bean.Car">

    <property name="name" value="兰博基尼"></property>

    <property name="color" value="黄色"></property>

</bean>

构造函数注入

 

准备带有参数的构造

 

<bean name="user2" class="com.jinghang.bean.User">

    <!-- name属性:构造函数参数名 -->

    <!-- index属性:构造函数参数索引  -->

    <!-- type属性:构造函数参数类型 -->

    <!-- 上述三个属性不必全部出现,根据情况选择即可 -->

    <constructor-arg name="name"  value="张三" index="0" type="java.lang.String"></constructor-arg>

    <constructor-arg name="car" ref="car"></constructor-arg>

</bean>

 

p名称空间注入(了解)

 

<!-- p空间注入   走set方法

        1.导入p空间名称 xmlns:p="http://www.springframework.org/schema/p"

        2.使用p:属性完成注入

            |-值类型 : p:属性名=""

            |-对象类型:p:属性名-ref="bean名称"

      -->

    <bean name="user3" class="com.jinghang.bean.User"    p:name="jack" p:age="20" p:car-ref="car">  

    </bean>

 

<!--car对象-->

<!--car对象配置到容器中 -->

    <bean name="car" class="com.jinghang.bean.Car">

        <property name="name" value="兰博基尼"></property>

        <property name="color" value="黄色"></property>

    </bean>

spel注入(了解)

 

<!-- spel注入:Spring Expression Language  spring表达式语言-->

<bean name="user4" class="com.jinghang.bean.User" >

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

    <property name="age" value="#{user3.age}"></property>

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

</bean>

4.6复杂类型注入

数组,listmap等等

public class CollectionBean {

    private Object[] arr;//数组类型注入

    private List list;//list/set类型注入

    private Map map;//map注入

    private Properties prop;// Properties 类型注入

}

数组

<bean name="cb"  class="com.jinghang.c_injection.CollectionBean">

        <!-- 如果数组中只准备一个值(对象),直接使用value|ref即可 -->

        <!-- 对象中数组名为arr -->

        <!-- <property name="arr" value="Tom"></property> -->

        <property name="arr">

            <array>

                <value>tom</value>

                <value>jerry</value>

                <ref bean="car"/>

            </array>

        </property>

</bean>

list

<!-- 如果list中只准备一个值(对象),直接使用value|ref即可 -->

        <!-- <property name="list" value="Tom"></property> -->

        <property name="list">

            <list>

                <value>tom</value>

                <value>Jerry</value>

                <ref bean="car"/>

            </list>

        </property>

map

<property name="map">

            <map>

                <entry key="1" value="abc"></entry>

                <entry key="2" value="def"></entry>

                <entry key-ref="car" value-ref="car"></entry>

            </map>

        </property>

prop

<property name="prop">

            <props>

                <prop key="abc">abc</prop>

                <prop key="def">def</prop>

                <prop key="ghi">ghi</prop>

            </props>

        </property>

5.整合web项目

 

 

6.使用注解配置spring

6.1步骤

1.为主配置文件引入新的命名空间(约束)

 

加入context,和之前快速入门完全一样,只是在添加namespace时,prefix不能为空。

导入spring下的aop

2.开启使用注解代替配置文件

 

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd ">

    <!-- 指定扫描com.jinghang.bean包下的所有类中的注解

        注意:扫描包时,会扫描指定包下的所有子孙包 -->

    <context:component-scan base-package="com.jinghang.bean"></context:component-scan>

</beans>

3.类中完成注解配置

@Component("user") //这四个注解完全一样,以下三个只是为了分层

    @Service("user")  //Service

    @Controller("user")  //Web

    @Repository("user")  //Dao

public class User {

}

4.代码测试

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

User u=(User) ac.getBean("user");

System.out.println(u);

6.2其他注解说明

scope

//指定对象作用范围

@Scope(scopeName="prototype")

public class User {}

值注入类型

//方法一

@Value("Tom")

//加到成员变量上,通过反射的Field赋值,破坏封装性

private  String name;

//方法二

@Value("Tom")

//通过set方法赋值

public void setName(String name) {

  this.name = name;

}

引用类型引入

 

@Autowired//自动装配

//问题,如果匹配多个类型一致的对象,将无法选择具体注入哪一对象

@Qualifier("car")//使用@Qualifier注解告诉spring容器自动装配哪个名称的对象

public Car car;

@Resource(name="car") //手动注入,指定注入哪个名称的对象

public Car car;

@Component("car")

public class Car {

@Value("法拉利")

private String name;

@Override

public String toString() {

    return "Car [name=" + name + "]";

}

}

 

初始化、销毁方法

 

@PostConstruct //在对象被创建之后调用,init-method

public void init() {

    System.out.println("初始化");

}

@PreDestroy //在对象销毁之前调用,destroy-method

public void destroy() {

    System.out.println("初始化");

}

7.STS插件

8.springjunit整合测试

导包(4+2+aop+test

配置注解

//创建容器

@RunWith(SpringJUnit4ClassRunner.class)

//指定容器使用配置文件

@ContextConfiguration("classpath:applicationContext.xml")

public class Deom {

    //将名为user的对象注入u变量中

    @Resource(name="user")

    private User u;

    @Test

    public void fun1() {

        System.out.println(u);

    }

}

9.aop

9.1aop思想

横向重复,纵向抽取

 

9.2Spring中的aop

Spring能够为容器中管理的对象生成动态代理对象

以前我们要使用动态代理,我们需要自己调用下面的方法生成对象Proxy.newProxyInstance(xx,xx,xx) 生成代理对象,Spring能够帮我们生成代理对象

9.2.1Spring实现aop原理

动态代理(优先)

被代理对象必须要实现实现接口,才能产生代理对象。如果没有接口不能使用动态代理技术。

cglib代理(没有接口使用)

第三方代理技术,cglib代理,可以对任何类实现代理,代理的原理是对目标对象进行继承代理。如果目标对象被final修饰,该类无法被cglib代理。

9.3aop名词解释

JoinPoint(连接点):在目标对象中,所有可以增强的方法。

PointCut(切入点):目标对象,已经增强的方法。

Advice(通知/增强):增强的代码

Target(目标对象):被代理对象

WeAVing(织入):将通知应用到切入点的过程

Proxy(代理):将通知织入到目标对象之后,形成代理对象

Aspect(切面):切入点+通知

10.aop演示(XML配置)

1.导包(4+2+2(spring_aop+spring_aspects)+2(com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar;com.springsource.org.aopalliance-1.0.0.jar))

2.准备目标对象

public class UserServiceImpl implements UserService{

    @Override

    public void save() {

        System.out.println("保存");

    }

    @Override

    public void delete() {

        System.out.println("删除");

    }

    @Override

    public void update() {

        System.out.println("更新");

    }

    @Override

    public void find() {

        System.out.println("查找");

    }

}

3.准备通知

前置通知 目标方法之前调用

后置通知 (如果出现异常不会调用) 在目标方法运行之后

环绕通知 在目标方法之前和之后都调用

异常拦截通知 如果出现异常,就会调用

后置通知 (无论是否出现异常都会调用) 在目标方法运行之后调用

public class MyAdvice {

 

    //前置通知,方法名是自己定义的

    public void before() {

        System.out.println("这是前置通知!");

    }

    //后置通知

    public void afterReturning() {

        System.out.println("这是后置通知(如果出现异常不会调用)");

    }

    //环绕通知

    public Object around(ProceedingJoinPoint pjp) throws Throwable {

        System.out.println("这是环绕通知之前的部分!");

        Object proceed = pjp.proceed();//调用目标方法

        System.out.println("这是环绕通知之后的部分!");

        return proceed;

    }

    //异常通知

    public void afterException() {

        System.out.println("异常出现了!");

    }

    //后置通知

    public void after() {

        System.out.println("这是后置通知(出现异常也会调用)");

    }

}

4.配置进行织入,将通知织入目标对象中

导入aop约束

xml文件中添加命名空间

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 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-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">

<!-- 准备工作:导入aop(约束)命名空间 -->

<!-- 1.配置目标对象 -->

    <bean name="userService" class="com.jinghang.proxy.UserServiceImpl"></bean>

<!-- 2.配置通知对象 -->

    <bean name="myAdvice" class="com.jinghang.proxy.MyAdvice"></bean>   

<!-- 3.配置将通知织入切入点对象 -->

    <aop:config>

    <!-- 配置切入点

        public void com.jinghang.proxy.UserServiceImpl.save()

         void com.jinghang.proxy.UserServiceImpl.save()

         * com.jinghang.proxy.UserServiceImpl.save()

         * com.jinghang.proxy.UserServiceImpl.*()

 

         * com.jinghang.proxy.*ServiceImpl.*(..)

         * com.jinghang.proxy..*ServiceImpl.*(..)

    -->

    <aop:pointcut expression="execution(* com.jinghang.proxy..*ServiceImpl.*(..))" id="pc"/>

        <aop:aspect ref="myAdvice">

            <!-- 指定为before方法作为前置通知 -->

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

            <!-- 后置 -->

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

            <!-- 环绕通知 -->

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

            <!-- 异常拦截通知 -->

            <aop:after-throwing method="afterException" pointcut-ref="pc"/>

            <!-- 后置 -->

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

        </aop:aspect>

    </aop:config>

</beans>

5.代码测试

//创建容器

@RunWith(SpringJUnit4ClassRunner.class)

//指定容器使用配置文件

@ContextConfiguration("classpath:com/jinghang/springaop/applicationContext.xml")

public class Deom {

 

    //将名为user的对象注入u变量中

    @Resource(name="userService")

    private UserService us;

 

    @Test

    public void fun1() {

 

        System.out.println(us);

        us.save();

    }

}

11.aop演示(注解)

1.导包

 

2.准备目标对象

 

3.准备通知

 

4.注解

 

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 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-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">

<!-- 准备工作:导入aop(约束)命名空间 -->

<!-- 1.配置目标对象 -->

    <bean name="userService" class="com.jinghang.proxy.UserServiceImpl"></bean>

<!-- 2.配置通知对象 -->

    <bean name="myAdvice" class="com.jinghang.proxy.MyAdvice"></bean>   

<!-- 3.注解配置 -->

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

</beans>

//表示是一个通知类

@Aspect

public class MyAdvice {

 

    @Pointcut("execution(* com.jinghang.proxy..*ServiceImpl.*(..))")

    public void pc() {}

 

    //前置通知

    //指定方法是前置通知,并制定切入点

    @Before("MyAdvice.pc()")

    public void before() {

        System.out.println("这是前置通知!");

    }

    //后置通知

    @AfterReturning("execution(* com.jinghang.proxy..*ServiceImpl.*(..))")

    public void afterReturning() {

        System.out.println("这是后置通知(如果出现异常不会调用)");

    }

    //环绕通知

    @Around("execution(* com.jinghang.proxy..*ServiceImpl.*(..))")

    public Object around(ProceedingJoinPoint pjp) throws Throwable {

        System.out.println("这是环绕通知之前的部分!");

        Object proceed = pjp.proceed();

        System.out.println("这是环绕通知之后的部分!");

        return proceed;

    }

    //异常通知

    @AfterThrowing("execution(* com.jinghang.proxy..*ServiceImpl.*(..))")

    public void afterException() {

        System.out.println("异常出现了!");

    }

    //后置通知

    @After("execution(* com.jinghang.proxy..*ServiceImpl.*(..))")

    public void after() {

        System.out.println("这是后置通知(出现异常也会调用)");

    }

}

5.代码测试

 

12.Spring整合JDBC

12.1JDBCTemplate

spring中提供了一个可以操作数据库的对象,对象封装了jdbc技术。

DBUtilsQueryRunner非常相似

DBUtils中的QueryRunner非常相似

//C3P0的连接池设定

//1.准备连接池

ComboPooledDataSource dataSource=new ComboPooledDataSource();

dataSource.setDriverClass("com.mysql.jdbc.Driver");

dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/spring");    

dataSource.setUser("root");

dataSource.setPassword("123456");

//2.创建JDBC模板对象

JdbcTemplate jTemplate=new JdbcTemplate();

jTemplate.setDataSource(dataSource);

//3.书写sql,并执行

String sql="insert into t_user values(null,'babdd')";

jTemplate.update(sql);

12.2 JDBCTemplate连接数据库

1.导包:

4(spring-beans+spring-context+spring-core+spring-expression)+2(spring-logging+spring-log4j)

Junit整合(spring-test+spring-aop)

JDBC驱动+C3P0连接池

spring-jdbc+spring-tx事务

2.准备数据库

3.书写Dao

uqdate

query(sql, rse, args);

queryForObject(sql, rse, args);

//使用JDBC模板实现增删改查

public class UserDaoIml implements UserDao{

 

  //并且给jTemplate设置setter方法

    private JdbcTemplate jTemplate;

    @Override

    public void save(User u) {

        String sql="insert into t_user values(null,?)";

        jTemplate.update(sql, u.getName());

    }

 

    @Override

    public void delete(Integer id) {

        String sql="delete from t_user where id=?";

        jTemplate.update(sql, id);

    }

 

    @Override

    public void update(User u) {

        String sql="update t_user set name=? where id=?";

        jTemplate.update(sql, u.getName(),u.getId());

    }

 

    @Override

    public User getById(Integer id) {

        String sql="select * from t_user where id=?";

        return jTemplate.queryForObject(sql, new RowMapper<User>() {

 

            @Override

            public User mapRow(ResultSet rs, int arg1) throws SQLException {

                User user=new User();

                user.setId(rs.getInt("id"));

                user.setName(rs.getString("name"));

                return user;

            }}, id);

    }

 

    @Override

    public int getTotalCount() {

        String sql="select count(*) from t_user";

        Integer count = jTemplate.queryForObject(sql, Integer.class);

        return count;

    }

 

    @Override

    public List<User> getAll() {

        String sql="select * from t_user";

        return jTemplate.query(sql,new RowMapper<User>() {

 

            @Override

            public User mapRow(ResultSet rs, int arg1) throws SQLException {

                User user=new User();

                user.setId(rs.getInt("id"));

                user.setName(rs.getString("name"));

                return user;

            }});

    }

 

    public void setjTemplate(JdbcTemplate jTemplate) {

        this.jTemplate = jTemplate;

    }

}

4.spring配置

 

依赖关系

注意三者的依赖关系,UserDaoImpl需要jdbcTemplate,jdbcTemplate需要datasource连接池,根据依赖关系,从下往上配置,显示dataSource连接池,再是jdbcTemplate,最后是UserDao

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd ">

<!-- 1.将连接池放入spring容器中 -->

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

    <property name="jdbcUrl" value="jdbc:mysql:///spring"></property>

    <property name="driverClass" value="com.mysql.jdbc.Driver"></property>

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

    <property name="password" value="123456"></property>

</bean>

<!-- 2.JDBCTemplate放入spring容器中 -->

  <!--JDBCTemplate需要datasource连接池 -->

<bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">

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

</bean>

<!-- 3.UserDao放入spring容器中 -->

  <!--UserDaoIml需要jdbctemplate-->

<bean name="userDao" class="com.jinghang.template.UserDaoIml">

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

</bean>

</beans>

5.测试

 

package com.jinghang.test;

 

import javax.annotation.Resource;

 

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

 

import com.jinghang.bean.User;

import com.jinghang.template.UserDao;

 

//创建容器

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration("classpath:applicationContext.xml")

public class Demo {

 

    //将名为userDao的对象注入ud变量中

        @Resource(name="userDao")

    private UserDao ud;

 

    @Test

    public void fun1() {

        User u=new User();

        u.setName("Jerry");

        ud.save(u);

    }

    @Test

    public void fun2() {

 

        ud.delete(1);

    }

    @Test

    public void fun3() {

        User u=new User();

        u.setId(4);

        u.setName("YYY");

 

        ud.update(u);

    }

    @Test

    public void fun4() {

 

        System.out.println(ud.getById(4));

    }

    @Test

    public void fun5() {

 

        System.out.println(ud.getAll());

    }

 

}

6.继承JDBCDaoSupport

 

根据连接池创建JDBC模板

不需要手动准备JDBC模板,从父类方法中获得即可

xml中不需要配置模板了

package com.jinghang.template;

 

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.List;

 

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.jdbc.core.RowMapper;

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

 

import com.jinghang.bean.User;

//使用JDBC模板实现增删改查

 

public class UserDaoIml extends JdbcDaoSupport implements UserDao{

 

 

@Override

public void save(User u) {

    String sql="insert into t_user values(null,?)";

    super.getJdbcTemplate().update(sql, u.getName());

}

 

@Override

public void delete(Integer id) {

    String sql="delete from t_user where id=?";

    super.getJdbcTemplate().update(sql, id);

}

 

@Override

public void update(User u) {

    String sql="update t_user set name=? where id=?";

    super.getJdbcTemplate().update(sql, u.getName(),u.getId());

}

 

@Override

public User getById(Integer id) {

    String sql="select * from t_user where id=?";

    return super.getJdbcTemplate().queryForObject(sql, new RowMapper<User>() {

 

        @Override

        public User mapRow(ResultSet rs, int arg1) throws SQLException {

            User user=new User();

            user.setId(rs.getInt("id"));

            user.setName(rs.getString("name"));

            return user;

        }}, id);

}

 

@Override

public int getTotalCount() {

    String sql="select count(*) from t_user";

    Integer count = super.getJdbcTemplate().queryForObject(sql, Integer.class);

    return count;

}

 

@Override

public List<User> getAll() {

    String sql="select * from t_user";

    return super.getJdbcTemplate().query(sql,new RowMapper<User>() {

 

        @Override

        public User mapRow(ResultSet rs, int arg1) throws SQLException {

            User user=new User();

            user.setId(rs.getInt("id"));

            user.setName(rs.getString("name"));

            return user;

        }});

}

}

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd ">

<!-- 1.将连接池放入spring容器中 -->

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

    <property name="jdbcUrl" value="jdbc:mysql:///spring"></property>

    <property name="driverClass" value="com.mysql.jdbc.Driver"></property>

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

    <property name="password" value="123456"></property>

</bean>

<!-- 2.JDBCTemplate放入spring容器中 -->

<!-- <bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">

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

</bean> -->

<!-- 3.UserDao放入spring容器中 -->

<bean name="userDao" class="com.jinghang.template.UserDaoIml">

    <!-- <property name="jTemplate" ref="jdbcTemplate"></property>   -->

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

</bean>

</beans>

7.改进:使用配置文件

 

db.properties src目录下

 

 jdbc.jdbcUrl=dbc:mysql:///spring

 jdbc.driverClass=com.mysql.jdbc.Driver

 jdbc.user=root

 jdbc.password=123456

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd ">

    <!-- 0.读取配置文件 -->

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

    <!-- 1.将连接池放入spring容器中 -->

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

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

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

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

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

    </bean>

    <!-- 2.JDBCTemplate放入spring容器中 -->

    <!-- <bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">

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

    </bean> -->

    <!-- 3.UserDao放入spring容器中 -->

    <bean name="userDao" class="com.jinghang.template.UserDaoIml">

        <!-- <property name="jTemplate" ref="jdbcTemplate"></property>   -->

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

    </bean>

</beans>

13.Spring与事务

13.1事务的概念

回顾知识

 

事务特性

 

事务并发问题

 

事务的隔离级别

事务操作对象

 

spring封装了事务管理的代码:打开事务,提交事务,回滚事务。

因为在不同平台,操作事务的代码各不相同,spring提供了一个接口PlatformTransactionManager 接口,里面有许多实现类:如JDBCDataSourceTransactionManager,在spring中事务管理最为核心的对象:TransactionManager

事务的隔离级别,1.读未提交;2.读已提交;3.可重复读;4.串行化

是否只读,true(只读) false

事务传播行为:决定业务方法之间调用,事务该如何处理。有七种,默认为PROPAGION_REQUIRED:支持当前事务,如果不存在,就新建一个(默认,99.9%以上概率)

13.2事务环境准备

1.接口

package com.ali.dao;

 

public interface AccountDao {

 

    //加钱

    void increaseMoney(Integer id, Double money);

    //减钱

    void decreaseMoney(Integer id,Double money);

 

}

2.准备数据库

3.实现接口

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

 

public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {

 

    @Override

    public void increaseMoney(Integer id, Double money) {

        super.getJdbcTemplate().update("update t_account set money =money+? where id=?",money,id);

 

    }

 

    @Override

    public void decreaseMoney(Integer id, Double money) {

        // TODO Auto-generated method stub

        super.getJdbcTemplate().update("update t_account set money =money-? where id=?",money,id);

    }

 

}

4.service层配置

package com.ali.service;

 

public interface AccountService {

 

    void transfer(Integer from ,Integer to,Double money);

}

 

package com.ali.service;

 

import com.ali.dao.AccountDao;

 

public class AccountServiceImpl implements AccountService {

 

    //注意此名字要与xml中的名字一致,否则无法注入

    private AccountDao accountDao;

    @Override

    public void transfer(Integer from, Integer to, Double money) {

        // TODO Auto-generated method stub

        ad.decreaseMoney(from, money);

        ad.increaseMoney(to, money);

    }

 

    //set方法注入,

    public void setAccountDao(AccountDao aDao) {

        this.accountDao = aDao;

    }

}

5.xml配置(一开始不了解可以在图上画一下有几个对象以及他们之间的依赖关系,然后从下向上配置)

 

 

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">

    <!-- 1.dataSource -->

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

        <property name="jdbcUrl" value="jdbc:mysql:///spring"></property>

        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>

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

        <property name="password" value="123456"></property>

    </bean>

    <!-- 2.dao -->

    <bean name="accountDao" class="com.ali.dao.AccountDaoImpl">

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

    </bean>

    <!-- 3.service -->

    <bean name="accountService" class="com.ali.service.AccountServiceImpl">

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

    </bean>

</beans>

6.事务管理:xml配置;注释配置

 

配置事务的核心管理器,依赖于连接池

</bean>

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

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

</bean>

xml配置

 

此时,通知由SpringAop提供,代理对象account已经写好,还有织入(配置)就可以完成。

 

导包:4+2+2(aop+aspect)+aop联盟+weaving织入包

 

导入新的约束(tx)

 

beans:最基本的 context:注解,读取properties配置 aop:配置aop tx:配置事务空间

配置通知

 

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">

    <!-- 指定spring读取db.properties配置 -->

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

    <!--事务核心管理器,封装了所有事务操作. 依赖于连接池  -->

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

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

    </bean>

    <!-- 配置事务通知 -->

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

        <tx:attributes>

            <!-- 以方法为单位,指定方法应用什么事务属性

            isolation:隔离级别

            propagation:传播行为

            read-only:是否只读

         -->

            <tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /><!-- 指定方法 -->

            <tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /><!--企业中一般使用如下通配符 -->

            <tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />

            <tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />

            <tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />

            <tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />

            <tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />

            <tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />

            <tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />

        </tx:attributes>

    </tx:advice>

    <!-- 配置织入 -->

    <aop:config>

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

        <aop:pointcut expression="execution(* com.ali.service.*ServiceImpl.*(..))" id="txPc"/>

        <!-- 配置切面 : 通知+切点

            advice-ref:通知的名称

            pointcut-ref:切点的名称

     -->

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

    </aop:config>

    <!-- 1.将连接池 -->

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

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

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

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

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

    </bean>

 

    <!-- 2.dao -->

    <bean name="accountDao" class="com.ali.dao.AccountDaoImpl">

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

    </bean>

    <!-- 3.service -->

    <bean name="accountService" class="com.ali.service.AccountServiceImpl">

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

    </bean>

</beans>

代码测试

 

注解配置

 

导包

 

引入新的约束(tx)

 

开启注解管理事务 <!-- 开启使用注解管理aop事务 --><tx:annotation-driven/>

 

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">

    <!-- 指定spring读取db.properties配置 -->

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

    <!--事务核心管理器,封装了所有事务操作. 依赖于连接池  -->

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

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

    </bean>

    <!-- 开启使用注解管理aop事务 -->

    <tx:annotation-driven/>

    <!-- 1.将连接池 -->

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

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

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

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

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

    </bean>

 

    <!-- 2.dao -->

    <bean name="accountDao" class="com.ali.dao.AccountDaoImpl">

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

    </bean>

    <!-- 3.service -->

    <bean name="accountService" class="com.ali.service.AccountServiceImpl">

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

    </bean>

</beans>

注解(注意:注解在类上加可以,在方法上加也可以)

 

public class AccountServiceImpl implements AccountService {

private AccountDao accountDao;

@Override

@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)

public void transfer(Integer from, Integer to, Double money) {

    // TODO Auto-generated method stub

    accountDao.decreaseMoney(from, money);

    accountDao.increaseMoney(to, money);

}

//set方法注入

public void setAccountDao(AccountDao aDao) {

    this.accountDao = aDao;

}

}

代码测试

 

 

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration("classpath:applicationContext2.xml")

public class Demo2 {

 

    @Autowired

    private AccountService aService;

    @Test

    public void fun1() {

        aService.transfer(1, 2, 100d);

    }

}

 

原文地址:https://www.cnblogs.com/liqian-/p/12069636.html