事务、类加载器、动态代理

本文介绍了事务、类加载器和动态代理相关知识。事务需保证多条SQL语句要么全成功要么全失败,有原子性等特性,还介绍了其隔离级别。类加载器负责将Java类加载到内存,有启动、扩展和系统类加载器。动态代理分静态和动态,JDK动态代理基于接口。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【事务、类加载器、动态代理】

事务

如果一个业务操作中多次访问了数据库,必须保证每条SQL语句都执行成功。如果其中有一条执行失败,所有已经执行过的代码必须回滚。回到没有执行前的状态。称为事务。要么所有的SQL语句全部执行成功,要么全部失败
一、事务的特性

1.原子性--------事务中的最小处理单位,要么全部一致成功,要么全部一起失败;
2. 一致性--------事务中每次查询的数据都是相同的,一致的,比如说:数据库中,张三有1000元,李四有1000元,数据是 2000元,下一次查询数据必须保持一致还是2000元;
3. 隔离性--------事务与事务中互不影响,相互独立执行;
4.** 持久性**--------事务一旦执行成功,数据提交将会永久保存到数据库;

事务的隔离级别

  1. 脏读---------一个事务读取另一个事务中未提交的数据
  2. 不可重复读------一个事务多次读取同一条记录,出现读取数据不一致的情况。一般因为另一个事务更新了这条
    记录而引发的。(也就是说每次读取数据都是不一致。)
  3. 幻读-------一个事务多次统计记录的行数,出现统计个数不一致的情况。因为另一个事务插入或删除表中
    的记录。(每一次读取数据条数都发生了变化)

设置隔离级别

  1. 四种隔离级别:

在这里插入图片描述

  1. 四种隔离级别起的作用:
    2.1. Serializable (串行化): 可以避免所有事务产生的并发访问的问题 效率及其低下
    2.2. Repeatable read (可重复读):会引发幻读的问题
    2.3. Read committed (读已提交):会引发不可重复读和幻读的问题
    2.4. Read uncommitted (读未提交): 所有事务中的并发访问问题都会发生

  2. 安全和性能对比
    隔离级别越高,安全性就越高。但性能越低。

  3. MySQL相关的命令:
    在这里插入图片描述

类加载器

所有的代码都是运行在内存中的,在Java中,所有的Java类都是通过类加载器加载到内存进行执行的
在这里插入图片描述
1、启动类加载器BootstrapClassLoader: 是嵌在JVM内核中的加载器,该加载器是用C++语言写的,主要负则加
载JAVA_HOME/lib下的类库,启动类加载器无法被应用程序直接使用。
2、扩展类加载器Extension ClassLoader: 该加载器器是用JAVA编写,且它的父类加载器是Bootstrap,是由
sun.misc.Launcher$ExtClassLoader实现的,主要加载JAVA_HOME/lib/ext目录中的类库。开发者可以这几使
用扩展类加载器。
3、系统类加载器App ClassLoader: 系统类加载器,也称为应用程序类加载器,负责加载应用程序classpath目录
下的所有jar和class文件(第三方jar)。它的父加载器为Ext ClassLoader。

类加载器获取资源

通过类加载器可以获取src下的任意一个资源,此类加载器必须是 App ClassLoader 类加载器

public class Demo1 {
	  public static void main(String[] args) {
	    InputStream is = Demo1.class.getClassLoader().getResourceAsStream("jdbc.properties");
	 }
}

动态代理

代理有两种模式,静态代理和动态代理。
如果需要委托类处理某一业务,那么我们就可以先在代理类中统一处理然后在调用具体实现类。
按照代理的创建时期,代理类可以分为两种:
静态代理 :由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。
动态代理 :在程序运行时运用反射机制动态创建而成。

代理例子:租房。
在这里插入图片描述
实现同一接口:(第三方接口)

interface Service{ //接口
	void save();
	void update();
	void delete();
}

目标对象(房东)

class ServiceImpl implements Service{ //目标对象(被代理对象)
	@Override
	public void save() {
		System.out.println("保存数据");
	}
	@Override
	public void update() {
		System.out.println("修改数据");
	}
	@Override
	public void delete() {
		System.out.println("删除数据");
	}
}

测试类:(调用者----租房的用户)

public class Demo {
	public static void main(String[] args) throws Exception {
		/*
		最终返回一个代理对象,此代理对象对目标对象的所有方法都进行了代理
		最终执行代理对象的任何方法都会执行InvocationHandler中的invoke方法
		*/
		Service o = (Service) Proxy.newProxyInstance(
			/*
			传入目标对象的类加载器
			*/
			ServiceImpl.class.getClassLoader(),
			/*
			传入目标对象的所有实现接口的字节码对象
			代理对象就是根据此接口字节码对象来指定代理方法,实现动态方法代理
			要不然目标对象增加一个方法,动态代理需要手动添加一个代理方法
			*/
			ServiceImpl.class.getInterfaces(),
			new InvocationHandler() {
				@Override
				/*
				proxy是代理对象
				method是目标对象的方法
				args是目标对象方法的参数
				*/
				public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
					System.out.println("增强的代码");
					// 因为method.invoke执行的是目标对象的具体方法,因此必须传入目标对象
					
					Object invoke = method.invoke(new ServiceImpl());
					System.out.println("增强的代码");
					return invoke;
				}
			}
		);
		// 代理对象执行save方法,最终会执行InvocationHandler中的invoke方法
		o.save();
	}
}

小结: JDK提供的动态代理是基于接口的,把目标对象所实现的所有接口的字节码对象传入方法中,JDK能在内存中
动态的帮我们创建一个对象,该对象实现的目标对象实现的所有方法。即保证目标对象的所有方法代理对象都能代理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值