为什么阿里规范中要求事务注解@Transactional中指定rollbackFor?
首先我们先得知道每个方法默认隐式抛出 runtimeException
再来看看异常的分类

可以看出Exception类下面除了runtimeException还有SQLException和ioException
如果方法没有抛出runtimeException 而是抛出 SQLException和ioException那么事务是不会回滚的
那么这就结束了吗?在我们编码过程中,如果方法要抛出一些可检查异常时是需要throws进行显式指定异常类的
那么问题来了,我们都知道方法签名中默认是throws RuntimeException,已知SqlException不是RuntimeException的子类,而是平级关系,按理说方法签名中需要指定出来才能通过编译

那么在调用层没有指定SqlException 时,他是如何抛出来的呢?
我们试一下


首先方法中没指定要抛出哪些异常,此时默认是RuntimeException
我故意在pojo类中写一个不存在的字段,查询后报错 SqlException

看一下栈堆

发现一个眼熟的方法

一个jdk动态代理类中指定抛出了顶级异常类。所以理论上说明可以通过代理后可以不指定异常,就可以抛出比RuntimeException大或者平级的异常?
现在咱们试一下,通过jdk动态代理来抛出异常
public interface People {
public People work(String workName);
public String time();
}
public class Student implements People{
@Override
public People work(String workName) {
System.out.println("工作内容是"+workName);
return this;
}
@Override
public String time() {
return "2018-06-12";
}
}
public class WorkHandler implements InvocationHandler {
private Object obj;
public WorkHandler(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy...");
method.invoke(this.obj, args);
throw new SQLException("我炸掉了");
}
}
public class Test {
public static void main(String[] args) {
People people = new Student();
InvocationHandler handler = new WorkHandler(people);
People peopleProxy= (People) Proxy.newProxyInstance(people.getClass().getClassLoader(),people.getClass().getInterfaces(),handler);
peopleProxy.work("努力工作...");
}
}
结果:

总结: 在常规使用过程中是不可能出现,没有指定异常就能抛出ioException和sqlException。这种情况下只有反射或者其他方式才能出现这种情况
浙公网安备 33010602011771号