Spring

1.什么是Spring?

Spring是一个开源的分层的javaSE/javaEE一站式的容器的轻量级的,解决业务逻辑层【Service】与web层和数据访问层之间的松耦合问题的容器框架。

2.Spring的结构组成

从下往上test,core容器,aop【面向切面编程】,web,data access

1.test部分只有一个模块:

spring-test:spring测试,提供junit与mock测试功能

spring-context-support:spring额外支持包,比如邮件服务、视图解析等

它们的依赖关系

 

2.core部分包含4个模块

spring-core:依赖注入IoC与DI的最基本实现

spring-beans:Bean工厂与bean的装配

spring-context:spring的context上下文即IoC容器

spring-expression:spring表达式语言

它们的完整依赖关系

3.aop部分包含4个模块

spring-aop:面向切面编程

spring-aspects:集成AspectJ

spring-instrument:提供一些类级的工具支持和ClassLoader级的实现,用于服务器spring-instrument-tomcat:针对tomcat的instrument实现

它们的依赖关系

4.web部分包含4个模块

spring-web:基础web功能,如文件上传

spring-webmvc:mvc实现

spring-webmvc-portlet:基于portlet的mvc实现

spring-struts:与struts的集成,不推荐,spring4不再提供

它们的依赖关系

5.data access部分包含5个模块

spring-jdbc:jdbc的支持

spring-tx:事务控制

spring-orm:对象关系映射,集成orm框架

spring-oxm:对象xml映射

spring-jms:java消息服务

它们的依赖关系

 

3.Spring的优点

1.方便解耦,简化开发:Spring是一个超级工厂(超级容器),可以将对象的创建和依赖关系交给Spring工厂去管理

2.AOP编程:Spring提供面向切面编程,可以方便的对程序进行运行监控、权限验证等操作

3.声明事务:只需要通过配置就可以完成对事务的管理,不需要手动编程

4.方便测试:Spring支持junit4,可以通过Spring注解方式测试程序

5.方便集成各种框架:Spring支持各种开源框架的集成。例如(struts、Hibernate、MyBaties等)

6.降低JavaEE API的使用难度:  Spring对JavaEE开发中非常难用的API进行封装,使这些开发API应用难度降低。

4.Spring的核心技术

1.IoC(Inverse of Control 反转控制):将java对象创建和维护权利交由Spring工厂进行管理和维护。

2.DI(依赖注入):将某一个java类中的依赖对象快速的添加到另一个java类中。

3.AOP(Aspect Oriented Programming 面向切面编程),基于动态代理的功能增强方式[给自己的程序中添加一些系统需求的处理【日志管理,数据的安全性检查.....】]。

4.事务管理的相关操作。

5.Spring整合/管理其他各层的框架【Spring集成web层SpringMVC/Spring整合数据访问层MyBatis】{SSM}

5.Spring的IoCInverse of Control 反转控制)

IoCInverse of Control 反转控制): java对象创建和维护权利交由Spring工厂进行管理和维护。

1.通过在Spring的配置文件中通过<bean>元素配置由Spring工厂所要创建的java对象。

2.如何从Sprign工厂所创建的众多对象中得到自己需要使用的java对象?

答案:首先得到Spring工厂对象,然后通过这个工厂对象提供的方法getBean(“”)将自己需要的对象得到。

3.Spring工厂对象有那些,如何创建Spring工厂对象,在创建Spring工厂对象的时候需要什么?

    1.BeanFactory接口----Spring工厂对象

    2.ApplicationContex接口------Spring工厂对象

ApplicationContext接口这个Spring工厂对象是BeanFactory接口的子接口

6.Bean实例化4种方式

无参数构造方法(开发最常用

package com.click369.javabean;
public class StudentBean {
    private  int stuid;
    private  String  stuname;
    private  int stuage;
    
public StudentBean(){}
.............
}

编写Spring的配置文件:【applicationContext.xml/自己起名】{src/main/resources}
<!-- 无参数构造方法实例化bean -->
<!-- id:对象名称 -->
<!-- class:被创建对象的java类的包名+类名 -->
<bean id="stu" class="com.click369.javabean.StudentBean"></bean>

测试
//创建Spring工厂对象
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//通过getBean方法从Spring工厂对象中得到需要的java类对象
StudentBean  stu= (StudentBean)applicationContext.getBean("stu");
//使用由Spring工厂对象实例化好的java对象
stu.setStuid(1001);
stu.setStuname("lisi");
stu.setStuage(24);
System.out.println("stu=="+stu.toString());

静态工厂方法实例化bean

静态工厂方法:在一个类中书写静态的方法,这个方法返回某个Bean的对象(在方法中创建Bean的对象)

package com.click369.javabean;
public class StudentBean {
    private  int stuid;
    private  String  stuname;
    private  int stuage;
    
public StudentBean(){}
.............
}
创建一个静态工厂方法类,提供一个静态方法,让这个静态方法返回一个实体类的对象
package com.click369.javabean;
/**
 * 静态工厂方法类
 * @author Administrator
 *
 */
public class StaticFactoryMethodClass {
	/**
	 * 静态方法,让这个静态方法返回一个实体类的对象
	 * @return
	 */
	public  static  StudentBean   getStaticStudentBean(){
		return new StudentBean();
	}
}

编写Spring配置
<!-- 静态工厂方法实例化bean的配置 -->
	<!-- id:对象名称 -->
	<!-- factory-method:配置静态工厂方法 -->
	<!-- class:配置静态工厂方法类【包名+类名】 -->
	<bean id="student" factory-method="getStaticStudentBean" class="com.click369.javabean.StaticFactoryMethodClass"></bean>

测试代码:
 ApplicationContext  applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
StudentBean  stu= applicationContext.getBean(StudentBean.class);
stu.setStuid(1002);
stu.setStuname("wangwu");
stu.setStuage(25);
System.out.println("stu=="+stu.toString())

实例工厂方法实例化bean

package com.click369.javabean;
public class StudentBean {
    private  int stuid;
    private  String  stuname;
    private  int stuage;
    
public StudentBean(){}
.............
}

创建一个工厂类,提供实例方法,这个实例方法返回java实体类的对象
package com.click369.javabean;

/**
 * 工厂类
 * @author Administrator
 *
 */
public class StudentFactory {
    /**
     * 实例方法,返回实体类对象
     * @return
     */
	public  StudentBean getStudentBean(){
		return new StudentBean();
	}
}
Spring配置文件的编写:
<!-- 实例工程方法实例化bean的配置 -->
	<!-- 创建实例工厂类对象 -->
	<bean id="studentFactory" class="com.click369.javabean.StudentFactory"></bean>
	<!-- 配置得到实体类对象 -->
	<!-- id:对象名称 -->
	<!-- factory-bean:实例工厂类对象 -->
	<!-- factory-method:实例工厂类中创建实体类的方法 -->
	<bean id="student" factory-bean="studentFactory" factory-method="getStudentBean"></bean>
测试:
ApplicationContext  applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
StudentBean  stu= applicationContext.getBean(StudentBean.class);
stu.setStuid(1002);
stu.setStuname("wangwu");
stu.setStuage(25);
System.out.println("stu=="+stu.toString());

FactoryBean接口方式实例化bean

FactoryBean是Spring提供的接口,专门用于对bean进行初始化操作的。

如果bean需要使用这种方式进行初始化,那么需要定义类实现这个FactoryBean接口,在实现类中复写getObject的方法。

package com.click369.javabean;
public class StudentBean {
    private  int stuid;
    private  String  stuname;
    private  int stuage;
    
public StudentBean(){}
.............
}
创建一个类,实现FactoryBean接口,重写getObject的方法,返回实体类对象。
package com.click369.factory;
import org.springframework.beans.factory.FactoryBean;
import com.click369.javabean.StudentBean;
public class CreateObject implements FactoryBean<StudentBean>{
	@Override
	public StudentBean getObject() throws Exception {
		return new StudentBean();
	}
	@Override
	public Class<?> getObjectType() {
		return StudentBean.class;
	}
}
Spring配置文件:
<!-- FactoryBean实例化Bean的配置 -->
	<!-- id:对象名称 -->
	<!-- class:实现FactoryBean接口的java类的包名+类名 -->
	<bean id="student" class="com.click369.factory.CreateObject"></bean> 
测试:
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.click369.javabean.StudentBean;
public class TestMain {
	public static void main(String[] args) {
		ApplicationContext  ac1=new ClassPathXmlApplicationContext("applicationContext.xml");
		StudentBean stu=ac1.getBean(StudentBean.class);
		stu.setStuid(1001);
		stu.setStuname("zhangsan");
		stu.setStuage(23);
		stu.setStuaddress("西安");
		System.out.println(stu.toString());
	}
}

7.FactoryBean接口与BeanFactory接口的区别

共同点:都是接口。

不同点:FactoryBeanSpring提供的专门用来实例化java类的接口。【创造】

        BeanFactory接口表示一个Spring工厂对象【Spring容器对象】,包含了实例化好的java类对象。【管理】

BeanFactory接口有一个常用的子接口ApplicationContext接口,我们通常使用ApplicationContext接口充当Spring工厂对象【Spring容器对象】。

8.bean的作用域

bean的作用域:主要是指Spring创建的Bean对象是单例、多例、request、session级别。

有点像JSP动作元素useBean的page/request/session/application.

singleton: 单例模式【在一个spring容器中,对象只有一个实例。(默认值)】

prototype:多例模式/原型模式【在一个spring容器中,存在多个实例,每次getBean 返回一个新的实例。】

request:该属性仅对HTTP请求产生作用,使用该属性定义Bean时,每次HTTP请求都会创建一个新的Bean,适用于WebApplicationContext环境。【一次请求一个对象】

session:该属性仅用于HTTP Session,同一个Session共享一个Bean实例。不同Session使用不同的实例。【同一次回话中的对象都是相同的】

global session:该属性仅用于HTTP Session,同session作用域不同的是,所有的Session共享一个Bean实例。【多个session共享一个对象】

<bean id=”对象名称” 
class=”被实例化的javabean类” 
scope=”singleton/prototype/request/session/global session”></bean>

1.singleton: 单例模式【在一个spring容器中,对象只有一个实例。(默认值)】
package com.click369.javabean;

public class StudentBean {
    private  int stuid;
    private  String  stuname;
    private  int stuage;
    
    public StudentBean(){}
    .......	
}

<!-- id:对象名称 -->
	<!-- class:被创建对象的java类的包名+类名 -->
	<!-- scope:设置作用域 -->
<bean id="stu" class="com.click369.javabean.StudentBean" scope="singleton"></bean>
或者
<bean id="stu" class="com.click369.javabean.StudentBean"></bean>


ApplicationContext  applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
		StudentBean stu1=applicationContext.getBean(StudentBean.class);
		StudentBean stu2=applicationContext.getBean(StudentBean.class);
		System.out.println("stu1=="+stu1.hashCode());
		System.out.println("stu2=="+stu2.hashCode());

 
prototype:多例模式/原型模式【在一个spring容器中,存在多个实例,每次getBean 返回一个新的实例。】
package com.click369.javabean;

public class StudentBean {
    private  int stuid;
    private  String  stuname;
    private  int stuage;
    
    public StudentBean(){}
    .......	
}

<!-- 无参数构造方法实例化bean的配置 -->
	<!-- id:对象名称 -->
	<!-- class:被创建对象的java类的包名+类名 -->
	<!-- scope:设置作用域 -->
	<bean id="stu" class="com.click369.javabean.StudentBean" scope="prototype"></bean>

ApplicationContext  applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
		StudentBean stu1=applicationContext.getBean(StudentBean.class);
		StudentBean stu2=applicationContext.getBean(StudentBean.class);
		System.out.println("stu1=="+stu1.hashCode());
		System.out.println("stu2=="+stu2.hashCode());

 

9.bean的生命周期

Spring工厂对象【Spring容器对象】负责创建对象,初始化对象,销毁对象。

也就是说任何一个交给Spring的Bean,它的生命周期统一由Spring容器维护。

测试Bean的创建生命周期:

package com.click369.javabean;

public class StudentBean {
    /**
     * 测试StudentBean类对象的创建
     */
    public StudentBean(){
    	System.out.println("测试StudentBean类对象的创建");
    }
}

	<!-- 无参数构造方法实例化bean的配置 -->
	<!-- id:对象名称 -->
	<!-- class:被创建对象的java类的包名+类名 -->
	<bean id="student" class="com.click369.javabean.StudentBean"></bean>

测试:
ApplicationContext  applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");

 

测试初始化:
package com.click369.javabean;

public class StudentBean {
    /**
     * 测试StudentBean类对象的创建
     */
    public StudentBean(){
    	System.out.println("测试StudentBean类对象的创建");
    }
    /**
     * 测试StudentBean类对象的初始化
     */
    public  void  initStudentBean(){
    	System.out.println("测试StudentBean类对象的初始化");
    }
}

	<!-- 无参数构造方法实例化bean的配置 -->
	<!-- id:对象名称 -->
	<!-- class:被创建对象的java类的包名+类名 -->
	<!-- init-method:配置对象的初始化方法 -->
	<bean id="student" class="com.click369.javabean.StudentBean" init-method="initStudentBean"></bean>
测试:
ApplicationContext  applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");

 

测试销毁:

Bean的销毁必须满足两个条件:

  1. bean必须是单例的。
  2. bean的所在的容器(Spring)必须手动关闭。
package com.click369.javabean;

public class StudentBean {
    /**
     * 测试StudentBean类对象的创建
     */
    public StudentBean(){
    	System.out.println("测试StudentBean类对象的创建");
    }
    /**
     * 测试StudentBean类对象的初始化
     */
    public  void  initStudentBean(){
    	System.out.println("测试StudentBean类对象的初始化");
    }
    /**
     * 测试StudentBean类对象的销毁
     */
    public  void  destroyStudentBean(){
    	System.out.println("测试StudentBean类对象的销毁");
    }
}

<!-- 无参数构造方法实例化bean的配置 -->
	<!-- id:对象名称 -->
	<!-- class:被创建对象的java类的包名+类名 -->
	<!-- init-method:配置对象的初始化方法 -->
<!-- destroy-method:配置对象的销毁方法 -->
<bean id="student" class="com.click369.javabean.StudentBean" init-method="initStudentBean"  destroy-method="destroyStudentBean"></bean>

测试类:
ApplicationContext  applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
		StudentBean stu1=(StudentBean)applicationContext.getBean("student");
		System.out.println("stu1=="+stu1.hashCode());
		//关闭容器
		((ClassPathXmlApplicationContext)applicationContext).close();

 
Bean的生命周期,先创建对象【构造方法执行】,再初始化【自己定义的初始化方法需要通过init-method属性配置】,当关闭容器的时候销毁对象【自己定义的销毁方法需要通过destroy-method属性配置】。

10.Spring的依赖注入是什么?实现方式有几种?每一种如何操作?

依赖注入--在调用者类中将被调用者类的对象,添加到调用者类中这个过程就是依赖注入。

          在这个过程中被调用者类的对象就是调用者类的依赖对象。

1.构造方法注入

创建被调用者类
package com.click369.javabean;
/**
 * 被调用者类
 * @author Administrator
 *
 */
public class PersonBean {

	 public  PersonBean(){
		 System.out.println("PersonBean--被调用者类的构造方法");
	 }
	 
	 public void testPerson(){
		 System.out.println("测试被调用者类");
	 }
}

调用者类
package com.click369.javabean;
/**
 * 调用者类
 * @author Administrator
 *
 */
public class StudentBean {
	//依赖对象
	public  PersonBean   personBean;
	
    public StudentBean(PersonBean   personBean){
    	System.out.println("StudentBean--调用者类的构造方法");
    	this.personBean=personBean;
}

    public  void  testStudent(){
    	System.out.println("测试StudentBean类");
    	personBean.testPerson();
    }
}
Spring配置文件
<!-- 创建被调用者类PersonBean -->
<bean id="person" class="com.click369.javabean.PersonBean"></bean>
<!-- 创建调用者类StudentBean -->
<bean id="student" class="com.click369.javabean.StudentBean">
	    <!-- 构造方法注入 -->
	    <!-- index:构造方法参数的索引值 -->
	    <!-- ref:引用对象 -->
	    <constructor-arg index="0" ref="person"></constructor-arg>
</bean>

测试
ApplicationContext  applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
StudentBean stu1=(StudentBean)applicationContext.getBean("student");
stu1.testStudent();

 

2.Set方法注入

被调用者类:
package com.click369.javabean;
/**
 * 被调用者类
 * @author Administrator
 *
 */
public class PersonBean {

	 public  PersonBean(){
		 System.out.println("PersonBean--被调用者类的构造方法");
	 }
	 
	 public void testPerson(){
		 System.out.println("测试被调用者类");
	 }
}

调用者类
package com.click369.javabean;
/**
 * 调用者类
 * @author Administrator
 *
 */
public class StudentBean {
	//依赖对象
	public  PersonBean   personBean;
	
    //为依赖对象提供一个set方法
	public void setPersonBean(PersonBean personBean) {
		this.personBean = personBean;
	}
	
    public  void  testStudent(){
    	System.out.println("测试StudentBean类");
    	personBean.testPerson();
    }
}
Spring配置文件:
<!-- 创建被调用者类PersonBean -->
	<bean id="person" class="com.click369.javabean.PersonBean"></bean>
	<!-- 创建调用者类StudentBean -->
	<bean id="student" class="com.click369.javabean.StudentBean">
	    <!-- set方法注入被调用者类 -->
	    <!-- name:成员变量名称【依赖对象名称】 -->
	    <!-- ref:引用对象 -->
	    <property name="personBean" ref="person"></property>
	</bean>

测试:
ApplicationContext  applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
		StudentBean stu1=(StudentBean)applicationContext.getBean("student");
		stu1.testStudent();

3.注解

@autowired/@resource

11.Spring的自动装配策略

Spring 提供了某些规则,可以对 bean 进行自动装配。<bean>autowire 属性可以指定自动装配的策略。

策略说明
byName根据名称进行匹配。
byType根据类型进行匹配。假设 Book 有一个 Author 类型的属性,如果容器中找到 Author 类型的 Bean 时,就会自动把它装配给 Book 的 Author 属性。
constructor也是根据类型进行匹配,只不过指的是构造函数的情况。假设 Book 有一个构造函数,它有一个 Author 类型的入参;如果容器中找到 Author 类型的 Bean 时,就会自动装配;如果没有找到,则抛出异常。
autodetect如果 Bean 提供了默认的构造函数,则采用 byType 方式;如果没有,则采用 constructor 方式。

<beans> 元素存在 default-autowire 属性,可以设置全局性的自动装配类型;如果为 no,则表示不启用自动装配;还有这些值:byName、byType、constructor 与 autodetect。


在实践中很少在 XML 中开启自动装配功能,而基于注解的配置方式默认采用的是 byType 自动装配策略。

12.autowired和resource的区别

1、共同点

两者都可以写在字段和setter方法上。两者如果都写在字段上,那么就不需要再写setter方法。

2、不同点

(1)@Autowired

@Autowired为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired;只按照byType注入

 

(2)@Resource

@Resource()默认按照ByName自动注入,由J2EE提供,需要导入包javax.annotation.Resource。@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。

13.@Component注解

spring注解中@component就是bai说把这个类交给Spring管理,又一次起个名字叫userManager,因为不清楚这个类是dao属于哪个层面,所以就用@Component。

14.什么是AOP?

AOP (Aspect Oriented Programing) 称为:面向切面编程,它是一种编程思想。

AOP 思想: 基于代理思想,对原来目标对象,创建代理对象,在不修改原对象代码情况下,通过代理对象,调用增强功能的代码【系统需求方法】,从而对原有业务方法进行增强。

AOP的底层是动态代理机制【CGLIB动态代理】。

基于两种动态代理机制: JDK动态代理和CGLIB动态代理。

JDK动态代理:基于接口的代理,会生成目标对象的接口的子对象【实现接口的类】

CGLIB动态代理:基于类的代理,会生成目标对象的子对象。【无论是继承父类还是实现接口所产生的类】

15.AOP相关的概念

joinpoint(连接点):指那些被拦截到的点。在spring中指的可以被代理(增强)的方法。【业务类中的业务需求方法】

poingcut(切入点):对哪些连接点进行拦截的定义。在Spring中指的真正需要被代理(增强)的方法。

advice(通知/增强):指拦截到连接点之后要做的事情。真正增强的那些代码(逻辑)。

         通知/增强分为:

                  前置通知,后置通知,异常通知,最终通知,环绕通知。

aspect(切面):是切入点和通知/增强的结合过程。

introduction(引介):一种特殊的通知在不修改类代码的前提下,introduction可以在运行期为类动态地添加一些方法或者字段。

target(目标对象):代码的目标对象。

weaving(织入):把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入。而AspectJ采用编译期织入和类装在期织入。

proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类。

16.基于XML文件的AOP实现

基于XML文件的AOP实现

<aop:config>

                  <aop:pointcut expression="execution(* com.click369.service.impl.UserServiceImpl.insertService(..))"

                                              id="point1"/>

                  <aop:pointcut expression="execution(* com.click369.service.impl.UserServiceImpl.updateService(..))"

                                              id="point2"/>

                  <aop:pointcut expression="execution(* com.click369.service.impl.UserServiceImpl.deleteService(..))"

                                              id="point3"/>                

                  <aop:aspect ref="myAvice">

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

                          <aop:after-returning method="savaLog" pointcut-ref="point2"/>

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

                  </aop:aspect>

         </aop:config>

17.基于注解的Aop实现

基于注解的Aop实现

@Aspect

@Before("execution(* com.click369.service.impl.UserServiceImpl.insertService(..))")

@AfterReturning("execution(* com.click369.service.impl.UserServiceImpl.updateService(..))")

@Around("execution(* com.click369.service.impl.UserServiceImpl.deleteService(..))")

<!-- 开启aop注解  -->

<aop:aspectj-autoproxy />

18.切入点表达式

1.任意公共方法的执行:
executionpublic * *..))
2.任何一个名字以“set”开始的方法的执行:
execution* set*..))
3.AccountService接口定义的任意方法的执行:
execution* com.xyz.service.AccountService.*..))
4.service包中定义的任意方法的执行:
execution* com.xyz.service.*.*..))
5.service包或其子包中定义的任意方法的执行:
execution* com.xyz.service..*.*..))
6.service包中的任意连接点(在Spring AOP中只是方法执行):
withincom.xyz.service.*
7.service包或其子包中的任意连接点(在Spring AOP中只是方法执行):
withincom.xyz.service..*
8.实现了AccountService接口的代理对象的任意连接点 (在Spring AOP中只是方法执行):
thiscom.xyz.service.AccountService
'this'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得代理对象在通知体内可用。
9.实现AccountService接口的目标对象的任意连接点 (在Spring AOP中只是方法执行):
targetcom.xyz.service.AccountService
'target'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得目标对象在通知体内可用。
10.任何一个只接受一个参数,并且运行时所传入的参数是Serializable 接口的连接点(在Spring AOP中只是方法执行)
argsjava.io.Serializable
'args'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得方法参数在通知体内可用。
请注意在例子中给出的切入点不同于 execution(* *(java.io.Serializable)) args版本只有在动态运行时候传入参数是Serializable时才匹配,而execution版本在方法签名中声明只有一个 Serializable类型的参数时候匹配。
11.目标对象中有一个 @Transactional 注解的任意连接点 (在Spring AOP中只是方法执行)
@targetorg.springframework.transaction.annotation.Transactional
'@target'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
12.任何一个目标对象声明的类型有一个 @Transactional 注解的连接点 (在Spring AOP中只是方法执行):
@withinorg.springframework.transaction.annotation.Transactional
'@within'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
13.任何一个执行的方法有一个 @Transactional 注解的连接点 (在Spring AOP中只是方法执行)
@annotationorg.springframework.transaction.annotation.Transactional
'@annotation'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
14.任何一个只接受一个参数,并且运行时所传入的参数类型具有@Classified 注解的连接点(在Spring AOP中只是方法执行)
@argscom.xyz.security.Classified
'@args'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
15任何一个在名为'tradeService'Spring bean之上的连接点 (在Spring AOP中只是方法执行):
beantradeService
16.任何一个在名字匹配通配符表达式'*Service'Spring bean之上的连接点 (在Spring AOP中只是方法执行):
bean*Service

19.什么事务?

对数据库的一系列操作中,保证同时成功或者同时失败。不能出现成部分成功,失败部分的情况。而这一些列操作称为数据库的事务

20.数据库的事务有4大特征【ACID

原子性:指事务是一个不可分割的工作单位,事务的操作要么都发生,要么都不发生.

一致性:事务前后数据的完整性必须保持一致。

隔离性:指多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务干扰,多个并发之间的数据要相互隔离。

持久性:指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其又任何影响。简称ACID。其中隔离性最重要。

21.事务的隔离性

使用Java操作的时候设置隔离级别由高到低分别为:

Serializable:可避免脏读、不可重复读、虚读情况的发生。

Repeatable read:可避免脏读、不可重复读情况发生。(可重复读)

Read committed:可避免脏读情况的发生。(读已提交)

Read uncommitted:最低级别,以上情况均为无法保证。(读未提交)

22.Spring的声明式事务管理方式

1.基于xml方式的事物管理操作

  

数据库中创建t_account账户表,模拟转账,演示spring的事务控制。
create table t_account(
account_id int primary key auto_increment,
user_name varchar(20),
money int
);
insert  into  t_account values(null,'刘能',10000);
insert  into  t_account values(null,'赵四',10000);
 
Spring+MyBatis工程结构
1.	创建工程导入依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.click369.springaop</groupId>
	<artifactId>SpringAOPDemo1</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>5.1.5.RELEASE</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-context-support -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>5.1.5.RELEASE</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
			<version>5.1.5.RELEASE</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
		<dependency>
			<groupId>aopalliance</groupId>
			<artifactId>aopalliance</artifactId>
			<version>1.0</version>
		</dependency>
		<!-- spring_tx -->
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>5.1.5.RELEASE</version>
		</dependency>
		<!-- spring-jdbc -->
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>5.1.5.RELEASE</version>
		</dependency>
		<!-- MyBatis依赖 -->
		<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.4.6</version>
		</dependency>
		<!-- mybatis-spring 整合包 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>1.3.1</version>
		</dependency>
		<!--druid 阿里的连接池 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.7</version>
		</dependency>
		<!-- mysql数据库驱动 -->
		<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.38</version>
		</dependency>
	</dependencies>
	<!-- 配置插件 -->
	<build>
		<plugins>
			<!-- 配置jdk1.8的编译插件 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.2</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>
2.转账接口
package com.click369.mapper;

import java.util.Map;

/**
 * 转账接口
 * @author Administrator
 *
 */
public interface TransferMapper {
	    // 加钱
		public void addMoney(Map  param);
		// 减钱
		public void lessMoney(Map  param);
}
3.在src/main/resources下创建mapper文件夹,mapper文件夹中创建Sql映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.click369.mapper.TransferMapper">
<!-- 编写加钱的sql -->
	<update id="addMoney" parameterType="hashMap">
		update t_account set money = money + #{number} where user_name = #{username}
	</update>
	<!-- 编写减钱的sql -->
	<update id="lessMoney" parameterType="hashMap">
		update t_account set money = money - #{number} where user_name = #{username}
	</update>
</mapper>
4.	创建业务访问接口以及实现类
package com.click369.service;
/**
 * 转账业务访问接口
 * @author Administrator
 *
 */
public interface TransferService {
	/**
	 * 转账方法
	 * @throws Exception
	 */
	void transfer()throws Exception;
}


package com.click369.service.impl;

import java.util.HashMap;
import java.util.Map;

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

import com.click369.mapper.TransferMapper;
import com.click369.service.TransferService;
/**
 * 转账业务实现类
 * @author Administrator
 *
 */
@Service("transferService")
public class TransferServiceImpl implements TransferService {
    //定义依赖对象
    @Autowired
	private  TransferMapper  transferMapper;

	@Override
	public void transfer() throws Exception {
		//从刘能的账户减少1000元,给赵四的账户增加1000元
		Map param1=new HashMap();
		param1.put("number", 1000);
		param1.put("username", "刘能");
		transferMapper.lessMoney(param1);
		//int i=10/0;
		Map param2=new HashMap();
		param2.put("number", 1000);
		param2.put("username", "赵四");	
		transferMapper.addMoney(param2);
	}
}
5.	创建数据库链接资源
mydriver = com.mysql.jdbc.Driver
myurl = jdbc:mysql://127.0.0.1:3306/test
myusername = root
mypassword = 123456
6.	配置Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	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/aop 
	http://www.springframework.org/schema/aop/spring-aop.xsd
	http://www.springframework.org/schema/context 
	http://www.springframework.org/schema/context/spring-context.xsd
	http://www.springframework.org/schema/tx
	http://www.springframework.org/schema/tx/spring-tx.xsd">
	<!-- 读取数据库链接字符串的资源文件 -->
	<context:property-placeholder location="classpath:mydatabase.properties"/>
	<!-- 配置数据源 com.alibaba.druid.pool.DruidDataSource -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
		<property name="driverClassName" value="${mydriver}"></property>
		<property name="url" value="${myurl}"></property>
		<property name="username" value="${myusername}"></property>
		<property name="password" value="${mypassword}"></property>
	</bean>
	<!-- 配置SqlSessionFactory "org.mybatis.spring.SqlSessionFactoryBean" -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<property name="mapperLocations" value="classpath:mapper/*Mapper.xml"></property>
	</bean>
	<!--扫描所有Mapper接口-->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	     <property name="basePackage" value="com.click369.mapper"/>
	     <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
	</bean>

	<!-- 配置spring的事务管理 -->
	<!-- 1.创建事务管理器对象-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 需要配置数据源 -->
		<property name="dataSource" ref="dataSource" />
	</bean>
	<!-- 2.创建事务-->
	<!--id:事务名称  -->
	<!--transaction-manager:事务管理器对象-->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<!--  使用method配置是事务控制的方法,method的其他属性默认即可 -->
			<tx:method name="transfer"/>
		</tx:attributes>
	</tx:advice>
	<!-- 3.通过aop将上面创建好的事物,作用到指定的业务方法中 -->
	<aop:config>
		<aop:pointcut expression="execution(* com.click369.service.impl.TransferServiceImpl.transfer(..))" id="point1"/>
		<!-- aop:advisor专门配置事务对象 -->
		<aop:advisor advice-ref="txAdvice" pointcut-ref="point1"/>
	</aop:config>

	<!-- 开启Spring主解 -->
	<context:annotation-config></context:annotation-config>
	<!-- 配置扫描包 -->
	<context:component-scan base-package="com.click369.service.impl"></context:component-scan>
</beans>	
7.	测试代码
ApplicationContext  ac=new ClassPathXmlApplicationContext("applicationContext.xml");
TransferService  transferService=(TransferService)ac.getBean("transferService");
transferService.transfer();

7.基于注解方式的事物管理操作

1.在需要管理事务的方法或者类上面 添加@Transactional 注解  

package com.click369.service.impl;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.click369.mapper.TransferMapper;
import com.click369.service.TransferService;
/**
 * 转账业务实现类
 * @author Administrator
 *
 */
@Service("transferService")
//使用@Transactional注解来表示当前的类需要被spring的事务管理
@Transactional
public class TransferServiceImpl implements TransferService {
    //定义依赖对象
    @Autowired
	private  TransferMapper  transferMapper;

	@Override
	public void transfer() throws Exception {
		// 从刘能的账户减少1000元,给赵四的账户增加1000元
		Map param1=new HashMap();
		param1.put("number", 1000);
		param1.put("username", "刘能");
		transferMapper.lessMoney(param1);
		int i=10/0;
		Map param2=new HashMap();
		param2.put("number", 1000);
		param2.put("username", "赵四");	
		transferMapper.addMoney(param2);
	}

}

2.配置注解驱动事务管理(事务管理注解生效的作用)(需要配置对特定持久层框架使用的事务管理器)

<?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"
	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/aop 
	http://www.springframework.org/schema/aop/spring-aop.xsd
	http://www.springframework.org/schema/context 
	http://www.springframework.org/schema/context/spring-context.xsd
	http://www.springframework.org/schema/tx
	http://www.springframework.org/schema/tx/spring-tx.xsd">
	<!-- 读取数据库链接字符串的资源文件 -->
	<context:property-placeholder location="classpath:mydatabase.properties"/>
	<!-- 配置数据源 com.alibaba.druid.pool.DruidDataSource -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
		<property name="driverClassName" value="${mydriver}"></property>
		<property name="url" value="${myurl}"></property>
		<property name="username" value="${myusername}"></property>
		<property name="password" value="${mypassword}"></property>
	</bean>
	<!-- 配置SqlSessionFactory "org.mybatis.spring.SqlSessionFactoryBean" -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<property name="mapperLocations" value="classpath:mapper/*Mapper.xml"></property>
	</bean>
	<!--扫描所有Mapper接口-->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	     <property name="basePackage" value="com.click369.mapper"/>
	     <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
	</bean>
	<!-- 开启Spring主键 -->
	<context:annotation-config></context:annotation-config>
	<!-- 配置扫描包 -->
	<context:component-scan base-package="com.click369.service.impl"></context:component-scan>
	<!-- 配置事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<!-- 需要配置数据源 -->
		<property name="dataSource" ref="dataSource" />
	</bean>
	<!-- 开启事务注解 -->
	<!--  <tx:annotation-driven transaction-manager="transactionManager"/>-->
	<!-- 默认会找transactionManager为名称的事务管理类对应的bean,
		因此可以在配置tx:annotation-driven的时候省略transaction-manager属性 -->
	<tx:annotation-driven/>
</beans>	

3.测试:

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

                  TransferService  transferService=(TransferService)ac.getBean("transferService");

                  transferService.transfer();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值