为什么阿里规范中要求事务注解@Transactional中指定rollbackFor?

首先我们先得知道每个方法默认隐式抛出 runtimeException

再来看看异常的分类

可以看出Exception类下面除了runtimeException还有SQLException和ioException

如果方法没有抛出runtimeException 而是抛出 SQLExceptionioException那么事务是不会回滚的

那么这就结束了吗?在我们编码过程中,如果方法要抛出一些可检查异常时是需要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。这种情况下只有反射或者其他方式才能出现这种情况

posted on 2021-12-21 18:04  奋斗中的&小强  阅读(182)  评论(0)    收藏  举报

导航