目录
一、Spring简单介绍
spring是一个轻量级控制反转(IOC)和面向切面(AOP)的容器框架,它主要是为了解决企业应用开发的复杂性而诞生的
所谓IOC,对于spring框架来说,就是spring控制对象的生命周期和对象间的关系。IOC的另外一个名字叫做依赖注入(Dependency Injection),所谓依赖注入,就是由IOC容器在运行期间动态地将某种依赖关系注入到对象中。因此,依赖注入(DI)和控制反转(IOC)是从不同角度在描述同一件事情,指通过引入IOC容器,利用依赖关系注入的方式实现对象之间的解耦。二者在语义上区别在于:
-
IOC控制反转。说的是创建实例的控制权从代码控制剥离到IOC容器控制,实现就是在xml进行控制,侧重原理
-
DI依赖注入。说的是创建对象实例时,为这个对象注入属性值或其它对象实例,侧重实现
所谓AOP,即将系统分为系统服务和业务逻辑,主要意图是将日志记录、性能统计、异常处理等代码从业务逻辑中分离出来。通常通过AOP来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等,AOP已经成为一种非常有用的解决方案
spring是一个复杂、完整的框架体系,上述只是对spring的主要思想作了简要介绍。其中,IOC和AOP的实现都依赖与Java的反射机制,因此,接下来会先介绍一下什么是Java的反射机制
二、Java反射机制
Java语言允许通过程序化的方式间接对class的对象实例进行操作,class文件由类装载器装载后,在JVM中将形成一份描述class结构的元信息对象,通过该元信息对象可以获知class的结构信息,如构造函数、属性和方法
类装载器就是寻找类的字节码并构造出类在JVM内部表示的对象组件,主要工作由ClassLoader及其子类负责。ClassLoader是一个重要的Java运行时系统组件,它负责在运行时查找和装入class字节码文件。我们通过一个例子来进一步说明java反射机制
Car类:
public class Car {
private String brand;
private String color;
private int maxSpeed;
//1.默认构造函数
public Car(){
System.out.println("init car!!");
}
//2.带参构造函数
public Car(String brand, String color, int maxSpeed){
this.brand = brand;
this.color = color;
this.maxSpeed = maxSpeed;
}
//3.为带参方法
public void introduce(){
System.out.println("brand:" + brand + "; color:" + color + "; maxSpeed:" + maxSpeed);
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
}
ReflectTest类:
public class ReflectTest {
public static void main(String[] args) throws Throwable{
Car car1 = initByDefaultConst();
Car car2 = initByParamConst();
car1.introduce();
car2.introduce();
}
//通过无参构造器实例化对象并初始化
public static Car initByDefaultConst() throws Throwable{
//1.通过类装载器获取Car类对象
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class clazz = loader.loadClass("springIOC.reflect.Car");
//2.获取类的默认构造器对象并实例化Car
Constructor cons = clazz.getDeclaredConstructor((Class[]) null);
Car car = (Car)cons.newInstance();
//3.通过反射方法获取属性
Method setBrand = clazz.getMethod("setBrand", String.class);
setBrand.invoke(car, "奔驰");
Method setColor = clazz.getMethod("setColor", String.class);
setColor.invoke(car, "黑色");
Method setMaxSpeed = clazz.getMethod("setMaxSpeed", int.class);
setMaxSpeed.invoke(car, 200);
return car;
}
//通过有参构造器实例化对象并初始化
public static Car initByParamConst() throws Throwable{
//1.通过类装载器获取类对象
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class clazz = loader.loadClass("springIOC.reflect.Car");
//2.获取类的带有参数的构造器
Constructor cons = clazz.getDeclaredConstructor(new Class[]{String.class, String.class, int.class});
//3.使用带有参数的构造器实例化对象
Car car = (Car)cons.newInstance(new Object[]{"宝马", "绿色", 180});
return car;
}
}
运行结果如下:
这说明我们已经成功利用java的反射机制创建出了Car类的两个实例,并运行了它们的方法
三、Spring IOC机制
如前所述,Spring IOC机制指的是创建实例的控制权从代码控制剥离到IOC容器控制。而Spring初始化Bean共有三种方式,分别是使用构造函数来初始化Bean、使用静态工厂方式来初始化Bean以及使用实例工厂方式来初始化Bean。下面分别对这三种方式进行说明
3.1 使用构造器来实例化Bean
HelloWorld接口:
public interface HelloWorld {
public void sayHello();
}
HelloWorld实现类:
public class HelloWorldImpl implements HelloWorld{
private String message;
public HelloWorldImpl(){
this.message = "Hello World!";
}
public HelloWorldImpl(String message){
this.message = message;
}
@Override
public void sayHello() {
System.out.println(message);
}
}
配置文件:
<!--使用默认构造参数-->
<bean id="helloWorldWithNoArgs" class="springIOC.instanceA.HelloWorldImpl" />
<!--使用有参数构造函数-->
<bean id="helloWorldWithArgs" class="springIOC.instanceA.HelloWorldImpl">
<!--指定构造器参数-->
<constructor-arg index="0" value="Hello Args" />
</bean>
主函数:
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args){
sayHelloWithArgs();
sayHelloWithNoArgs();
}
//使用无参数构造器来实例化Bean
public static void sayHelloWithNoArgs(){
BeanFactory beanFactory = new ClassPathXmlApplicationContext("resource/conf-instanceA.xml");
HelloWorld helloWorld = beanFactory.getBean("helloWorldWithNoArgs", HelloWorld.class);
helloWorld.sayHello();
}
//使用有参数构造器来实例化Bean
public static void sayHelloWithArgs(){
BeanFactory beanFactory = new ClassPathXmlApplicationContext("resource/conf-instanceA.xml");
HelloWorld helloWorld = beanFactory.getBean("helloWorldWithArgs", HelloWorld.class);
helloWorld.sayHello();
}
}
运行结果如下:
这说明我们已经成功通过Spring IOC机制的构造函数方式创建了HelloWorldImpl的两个实例
3.2 使用静态工厂实例化Bean
使用静态工厂的方式除了指定必须的class属性外,还要指定factory-method属性来实例化Bean的方法,而且使用静态工厂方法也允许指定方法参数。Spring IOC容器将调用此属性指定的方法来获取Bean
示例中,HelloWorld接口和HelloWorldImpl类和3.1节一样,HelloWorldInstanceFactory类如下:
public class HelloWorldInstanceFactory {
public static HelloWorld newInstance(String message){
return new HelloWorldImpl(message);
}
}
配置文件如下:
<!--静态工厂方式-->
<bean id="helloWorldStaticFactory" class="springIOC.instanceB.HelloWorldInstanceFactory" factory-method="newInstance">
<!--指定构造器参数-->
<constructor-arg index="0" value="Hello Static Factory!" />
</bean>
主函数如下:
public class Main {
public static void main(String[] args){
helloWorldStaticFactory();
}
//使用静态工厂方法来实例化Bean
public static void helloWorldStaticFactory(){
//1.读取配置文件实例化一个IOC容器
BeanFactory beanFactory = new ClassPathXmlApplicationContext("resource/conf-instanceB.xml");
//2.从容器中获取Bean
HelloWorld helloWorld = beanFactory.getBean("helloWorldStaticFactory", HelloWorld.class);
//3.执行业务逻辑
helloWorld.sayHello();
}
}
运行结果如下:
这说明我们已经成功通过Spring IOC机制的静态工程方式创建了HelloWorldImpl类的对象
3.3 使用实例工厂来实例化Bean
使用实例工厂方式不能指定class属性,此时必须使用factory-bean属性来指定工厂bean,factory-method属性来指定实例化bean的方法。同时,使用实例工厂方法允许指定方法参数
示例中,HelloWorld接口和HelloWorldImpl类和3.1节一样,HelloWorldInstanceFactory类如下:
public class HelloWorldInstanceFactory {
public HelloWorld newInstance(String message) {
return new HelloWorldImpl(message);
}
}
xml配置文件如下:
<!--定义实例工厂Bean-->
<bean id="helloWorldInstanceFactory" class="springIOC.instanceC.HelloWorldInstanceFactory" />
<!--使用实例工程Bean创建Bean-->
<bean id="helloWorldInstance" factory-bean="helloWorldInstanceFactory" factory-method="newInstance">
<constructor-arg index="0" value="Hello Instance Factory"></constructor-arg>
</bean>
运行结果如下:
这说明我们已经成功通过Spring IOC机制的实例工程方式创建了HelloWorldImpl类的对象
3.4 Spring IOC实现原理
Spring IOC的实现原理利用的是Java的反射机制,它的工厂类会帮我们完成配置文件的读取、利用反射机制注入对象等工作,我们可以通过Bean的名称来获取对应的对象
下面通过一个示例来简单展示来它的实现机制。首先创建一个JavaBean类:
public class JavaBean {
private String userName;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
BeanFactory类:
public class BeanFactory {
private Map<String, Object> beanMap = new HashMap<String, Object>();
/**
* bean工厂的初始化,通过xml文件给对象注入相关属性
* @param xml xml配置文件
*/
public void init(String xml){
try{
//1.创建读取配置文件的reader对象
SAXReader reader = new SAXReader();
//2.获取当前线程中的类装载器对象
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
//3.从class目录下获取指定的xml文件
InputStream ins = classLoader.getResourceAsStream(xml);
Document doc = reader.read(ins);
Element root = doc.getRootElement();
Element foo;
//4.遍历xml文件中的bean实例
for(Iterator i=root.elementIterator("bean"); i.hasNext();){
foo = (Element) i.next();
//5.针对每个bean实例,获取bean的属性id和class
Attribute id = foo.attribute("id");
Attribute cls = foo.attribute("class");
//6.利用java反射机制,通过class名称获取class对象
Class bean = Class.forName(cls.getText());
//7.获取对应class信息
java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(bean);
//8.获取其属性信息
java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors();
//9.创建一个对象,并在接下来的代码中为对象的属性赋值
Object obj = bean.getDeclaredConstructor().newInstance();
//10.遍历该bean的property属性
for(Iterator ite=foo.elementIterator("property"); ite.hasNext();){
Element foo2 = (Element)ite.next();
//11.获取该property的name属性
Attribute name = foo2.attribute("name");
String value = null;
//12.获取该property的子元素value的值
for(Iterator ite1=foo2.elementIterator("value"); ite1.hasNext();){
Element node = (Element)ite.next();
value = node.getText();
break;
}
//13.利用java的反射机制调用对象的某个set方法,并将值设置进去
for(int k=0; k<pd.length; k++){
if(pd[k].getName().equalsIgnoreCase(name.getText())){
Method mSet = null;
mSet = pd[k].getWriteMethod();
mSet.invoke(obj, value);
}
}
}
//14.将对象放入beanMap中,其中key为id值,value为对象
beanMap.put(id.getText(), obj);
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
public Object getBean(String beanName){
Object obj = beanMap.get(beanName);
return obj;
}
public static void main(String[] args){
BeanFactory factory = new BeanFactory();
factory.init("resource/config-realize.xml");
JavaBean javaBean = (JavaBean)factory.getBean("javaBean");
System.out.println("userName=" + javaBean.getUserName());
System.out.println("password=" + javaBean.getPassword());
}
}
xml配置文件:
<bean id="javaBean" class="springIOC.realize.JavaBean">
<property name="userName">
<value>周杰伦</value>
</property>
<property name="password">
<value>19790118</value>
</property>
</bean>
3.5 Spring Bean的作用域
Spring Bean中所说的作用域,在xml配置文件中使用"scope"配置,指其创建的Bean对象相对于其它Bean对象的请求可见范围。常见的有以下两种:
-
singleton:Spring IOC中只会存在一个共享的Bean实例,所有对Bean的请求,只要id相匹配,则只会返回Bean的同一个实例
-
prototype:每次对该Bean进行请求时,都会创建一个新的Bean实例
下面通过一个例子来说明这两种作用域的区别。首先创建一个Car类:
public class Car {
private String color;
private String brand;
private double price;
public double getPrice(){
return price;
}
public void setPrice(double price){
this.price = price;
}
public String getBrand(){
return brand;
}
public void setBrand(String brand){
this.brand = brand;
}
public String getColor(){
return color;
}
public void setColor(String color){
this.color = color;
}
}
Boss类:
public class Boss {
private String name;
private Car car;
public Boss(){}
public Car getCar(){
return car;
}
public void setCar(Car car){
this.car = car;
}
@Override
public String toString(){
return "name:" + name + "\n car:" + car;
}
}
xml配置文件:
<bean id="car" class="springIOC.scope.Car" scope="singleton" />
<bean id="boss1" class="springIOC.scope.Boss" p:car-ref="car" />
<bean id="boss2" class="springIOC.scope.Boss" p:car-ref="car" />
<bean id="boss3" class="springIOC.scope.Boss" p:car-ref="car" />
主函数:
public class Main {
public static void main(String[] args){
BeanFactory beanFactory = new ClassPathXmlApplicationContext("resource/conf-scope.xml");
Boss boss1 = beanFactory.getBean("boss1", Boss.class);
Boss boss2 = beanFactory.getBean("boss2", Boss.class);
Boss boss3 = beanFactory.getBean("boss3", Boss.class);
System.out.println(boss1.getCar());
System.out.println(boss2.getCar());
System.out.println(boss3.getCar());
}
}
当scope="singleton"运行结果如下:
三个对象的地址是一样的,证明三次对Bean的请求返回的是同一个实例
当scope="prototype"运行结果如下:
三个对象的地址是不一样的,证明三次对Bean的请求返回的是不同的实例
四、Spring AOP机制
4.1 相关概念
概念 | 含义 |
---|---|
连接点 | 程序执行的某个特定位置,比如类初始化前、初始化后,方法执行前、执行后 |
切点 | 通过切点来定位特殊的连接点 |
增强 | 织入到目标类连接点上的一段代码 |
目标对象 | 增强对象的织入目标类 |
引介 | 引介是一种特殊的增强,它为类添加一些属性和方法 |
织入 | 将增强添加到目标类具体连接点的过程 |
代理 | 一个类被AOP织入增强后,会产生一个结果类,该类是融合了原类和增强逻辑的代理类 |
切面 | 由切点和增强组成,既包括了增强逻辑的定义,也包括了连接点的定义 |
4.2 利用proxy实现AOP功能
本小节是单纯针对AOP思想的实现,而不局限于Apring AOP。对于proxy类有一个使用前提,就是目标对象必须要实现接口,否则不能使用这个方法。下面通过一个示例来说明如何通过proxy类来实现AOP思想
StudengInterface接口:
public interface StudentInterface {
public void print();
}
StudentBean类:
public class StudentBean implements StudentInterface{
private String name;
public StudentBean(){}
public StudentBean(String name){
this.name = name;
}
@Override
public void print() {
System.out.println("Hello World!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
ProxyFactory类:
public class ProxyFactory implements InvocationHandler {
private Object stu;
public Object createStudentProxy(Object stu){
this.stu = stu;
return Proxy.newProxyInstance(stu.getClass().getClassLoader(), stu.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
StudentBean s = (StudentBean)stu;
Object object = null;
if(s.getName()!=null){
object = method.invoke(stu, args);
} else {
System.out.println("名称为空,代理类已经拦截!");
}
return object;
}
主函数:
public class Main {
public static void main(String[] args){
StudentInterface s1 = new StudentBean();
ProxyFactory factory = new ProxyFactory();
StudentInterface s2 = (StudentInterface)factory.createStudentProxy(s1);
s2.print();
}
}
运行结果如下:
4.3 利用CGLib实现AOP功能
CGLib(Code Generation Library)是一个开源项目,它是一个强大的、高性能、高质量的Code生成类库,可以在运行期间扩展Java类与实现Java接口。利用proxy创建的代理类和目标对象必须实现同一接口,使用CGLib则继承了目标对象
Student类:
public class StudentBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public StudentBean(){}
public StudentBean(String name){
this.name=name;
}
public void print() {
System.out.println("Hello World!");
}
}
CGLibProxyFactory类:
public class CGLibProxyFactory implements MethodInterceptor {
private Object object;
public Object createStudent(Object object){
this.object = object;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(object.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
StudentBean stu = (StudentBean)object;
Object result = null;
if(stu.getName()!=null){
result = methodProxy.invoke(object, args);
}else{
System.out.println("该方法已被拦截!");
}
return result;
}
}
主函数:
public class Main {
public static void main(String[] args){
StudentBean s1 = (StudentBean)(new CGLibProxyFactory()).createStudent(new StudentBean());
StudentBean s2 = (StudentBean)(new CGLibProxyFactory()).createStudent(new StudentBean("Leon"));
s1.print();
s2.print();
}
}
运行结果如下:
4.4 Spring利用注解方式实现AOP
Student类:
public class Student {
public String print(String name){
System.out.println(name);
return "Hello World";
}
}
StuInterceptor类:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
@Aspect
public class StuInterceptor {
@Pointcut("execution(* springAOP.aspect.Student.print(..))")
public void printMethod(){
}
@Before("printMethod()")
public void printBeforeAdvice(){
System.out.println("printBeforeAdvice!");
}
@AfterReturning(pointcut="printMethod()", returning="flag")
public void printAfterAdvice(String flag){
System.out.println("printAfterAdvice()!" + flag);
}
@After("printMethod()")
public void printFinallyAdvice(){
System.out.println("printFinally" +
"Advice!");
}
@Around("printMethod() && args(name)")
public Object printAroundAdvice(ProceedingJoinPoint pjp, String name) throws Throwable{
Object obeject = null;
if(name.equals("Jay Chou"))
pjp.proceed();
else
System.out.println("print()方法已经被拦截!!");
return obeject;
}
}
xml配置:
<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-3.1.xsd">
<aop:aspectj-autoproxy />
<bean id="stuInterceptor" class="springAOP.aspect.StuInterceptor"></bean>
<bean id="stu" class="springAOP.aspect.Student"></bean>
</beans>
主函数:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("resource/conf-aspect.xml");
Student stu = (Student)ctx.getBean("stu");
stu.print("Jay Chou");
}
}
运行结果如下:
4.5 Spring利用xml配置文件实现AOP
Student类和4.4小节的Student类一样。StuInterceptor类如下:
import org.aspectj.lang.ProceedingJoinPoint;
public class StuInterceptor {
public void printMethod(){
}
public void printBeforeAdvice(){
System.out.println("printBeforeAdvice!");
}
public void printAfterAdvice(String flag){
System.out.println("printAfterAdvice()!" + flag);
}
public void printFinallyAdvice(){
System.out.println("printFinally" + "Advice!");
}
public Object printAroundAdvice(ProceedingJoinPoint pjp, String name) throws Throwable{
Object obeject = null;
if(name.equals("Jay Chou"))
pjp.proceed();
else
System.out.println("print()方法已经被拦截!!");
return obeject;
}
}
xml配置文件如下:
<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-3.1.xsd">
<aop:aspectj-autoproxy />
<bean id="interceptor" class="springAOP.xml.StuInterceptor"></bean>
<bean id="stu" class="springAOP.xml.Student"></bean>
<aop:config>
<aop:aspect id="stuInterceptor" ref="interceptor">
<aop:before
pointcut="execution(* springAOP.xml.Student.print(..))"
method="printBeforeAdvice" />
<aop:after-returning
pointcut="execution(* springAOP.xml.Student.print(..)) and args(flag)"
method="printAfterAdvice" arg-names="flag"/>
<aop:after
pointcut="execution(* springAOP.xml.Student.print(..))"
method="printFinallyAdvice" />
<aop:around
pointcut="execution(* springAOP.xml.Student.print(..)) and args(name)"
method="printAroundAdvice" arg-names="pjp,name" />
</aop:aspect>
</aop:config>
</beans>
主函数:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("resource/conf-xml.xml");
Student stu = (Student)ctx.getBean("stu");
stu.print("Jay Chou");
}
}
运行结果如下:
五、Spring 中的事务管理
5.1 事务简介
• 事务管理是企业级应用程序开发中必不可少的技术, 用来确保数据的完整性和一致性.
• 事务就是一系列操作数据库的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用
• 事务的四个关键属性(ACID) (重点 重点 重点 重要事情说三遍!!!)
– 原子性(atomicity): 事务是一个原子操作, 由一系列动作组成. 事务的原子性确保动作要么全部完成(要么成功)要么完全不起作用(要么失败).
– 一致性(consistency): 一旦所有事务动作完成, 事务就被提交(commit). 数据和资源就处于一种满足业务规则的一致性状态中.
– 隔离性(isolation): 可能有许多事务会同时处理相同的数据, 因此每个事物都应该与其他事务隔离开来, 防止数据损坏.
– 持久性(durability): 一旦事务完成, 无论发生什么系统错误, 它的结果都不应该受到影响. 通常情况下, 事务的结果被写到持久化存储器中.
事务管理的问题
puhlic void purchase ( string isbn,string usernarme ) {
connection conn = null;
try {
conn = datasource. getconnection ( ) ;conn. setAutoCormit (false ) ;
// .. .
conn. commit( ) ;
}catch (sQLException e){
e. printstackTrace ( ) ;
if(conn != null) {
try {
conn.rollback ( ) ;
}catch ( SQLException e1) {
e1.printstackTrace ( );
}
}
throw new RuntimeException (e);
fina1ly{
if ( conn != nu11) {
try {
conn.close ( ):
}eateh (sQLException e){
e.printstackTrace ( ) ;
}
5.2 Spring 中的事务管理
• 作为企业级应用程序框架, Spring 在不同的事务管理 API 之上定义了一个抽象层. 而应用程序开发人员不必了解底层的事务管理 API, 就可以使用 Spring 的事务管理机制.
• Spring 既支持编程式事务管理, 也支持声明式的事务管理.
• 编程式事务管理: 将事务管理代码嵌入到业务方法中来控制事务的提交和回滚. 在编程式管理事务时, 必须在每个事务操作中包含额外的事务管理代码.
• 声明式事务管理: 大多数情况下比编程式事务管理更好用. 它将事务管理代码从业务方法中分离出来, 以声明的方式来实现事务管理. 事务管理作为一种横切关注点, 可以通过 AOP 方法模块化. Spring 通过 Spring AOP 框架支持声明式事务管理.
Spring 中的事务管理器
• Spring 从不同的事务管理 API 中抽象了一整套的事务机制. 开发人员不必了解底层的事务 API, 就可以利用这些事务机制. 有了这些事务机制, 事务管理代码就能独立于特定的事务技术了.
• Spring 的核心事务管理抽象是
• 它为事务管理封装了一组独立于技术的方法. 无论使用 Spring 的哪种事务管理策略(编程式或声明式), 事务管理器都是必须的.
Spring 中的事务管理器的不同实现 - *重要*
• 在应用程序中只需要处理一个数据源, 而且通过 JDBC 存取
• : 在 JavaEE 应用服务器上用 JTA(Java Transaction API) 进行事务管理
• :用 Hibernate 框架存取数据库
• ……
• 事务管理器以普通的 Bean 形式声明在 Spring IOC 容器中(事务交给IOC容器来管理)
5.3 @Transactional
用@Transactional注解声明式地管理事务
·除了在带有切入点,通知和增强器的Bean 配置文件中声明事务外,
Spring还允许简单地用@Transactional注解来标注事务方法.·为了将方法定义为支持事务处理的,可以为方法添加
@Transactional注解.根据Spring AOP基于代理机制,只能标注公有方法.
。可以在方法或者类级别上添加@Transactional注解.当把这个注
解应用到类上时,这个类中的所有公共方法都会被定义成支持事务处理的.
。在Bean配置文件中只需要启用<tx:annotation-drien>元素,并
为之指定事务管理器就可以了.
。如果事务处理器的名称是transactionManager,就可以在
<tx:annotation-driven>元秦中省略 transaction-manager属性.这个元秦会自动检测该名称的事务处理器
标签:指南,String,Spring,void,public,Bean,class,入门 From: https://blog.csdn.net/qq_41320700/article/details/143779152