Spring的AOP中抛出“自定义异常”的问题?

lbllbl 2012-04-16 10:46:16
各部分代码如下:

自定义异常类(和RuntimeException类完全一样,只是改了个名字)

public class MyException extends Exception
{
static final long serialVersionUID = -7034897190745766939L;

public MyException() {
super();
}

public MyException(String message) {
super(message);
}

public MyException(String message, Throwable cause) {
super(message, cause);
}

public MyException(Throwable cause) {
super(cause);
}
}

Spring的AOP切面程序

@Aspect
@Component
public class CheckSecurity
{
@Pointcut("execution(* add*(..))")
private void chkAdd() {};

@Before("chkAdd()")
public void check() throws Exception {
//throw new RuntimeException("出错退出");
throw new MyException("出错退出");
}
}

被AOP拦截的类

@Component
public class UserDao
{
public void addUser(String name) {
System.out.println("addUser");
}
}

测试代码

public class ChkTest
{
public static void main(String[] args)
{
ApplicationContext factory = new ClassPathXmlApplicationContext("check.xml");
UserDao dao = (UserDao)factory.getBean("userDao");
try{
dao.addUser("");
} catch(Exception e) {
System.out.println(e.getMessage());
}
}
}


执行后输出为:null

如果我把代码中:throw new MyException("出错退出"); 换成 throw new RuntimeException("出错退出");
执行后输出为:出错退出
这是为什么?MyException与RuntimeException都是一样的。

问题2:
我在测试代码中写 chatch(MyException e) ,提示以下错误:
Unreachable catch block for MyException. This exception is never thrown from the try statement body
要在被拦截的addUser方法后写 throws MyException才行?

...全文
1538 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
浅羊 2021-06-29
  • 打赏
  • 举报
回复

写给后面遇到同样问题的人看的。

我也遇到这种情况,我在aop的before中做了自定义参数校验,抛出自定义异常。测试时虽然打印了我在全局异常处理中的内容,但返回给前端的是普通的Exception系统异常,且控制台也多余地打印了Exception异常。

解决方法是,对于做切面的方法(如controller中要做入参校验的类),做异常捕获。如,方法后添加throw MyException。这样idea会报is never thrown的警告,但实际上是用上了的。

浅羊 2021-06-29
  • 举报
回复
@浅羊 还有一种解决方法,让自定义的异常`extends RuntimeException`而不是`Exception`。
lbllbl 2012-04-18
  • 打赏
  • 举报
回复
7楼的意思是不是说RuntimeException这个异常,是被赋予特殊功能的异常,在系统内部有特殊用途,系统对它有特殊处理。
安特矮油 2012-04-18
  • 打赏
  • 举报
回复
终于算是明白你的意思了,
这应该是因为RuntimeException跟普通编译期异常的在JVM处理的时候不一样的缘故吧。
你的MyException直接继承于Exception就算代码与RuntimeException一样,但是JVM内部的处理肯定是不一样的,因为你的MyException只是一个编译期的异常。

因为你catch的是addUser这个方法,但是这个方法却是没有异常,所以他只能catch到JVM运行时的异常,也就是RuntimeException,所以你的MyException无法获取到异常信息,因为他不是RuntimeException。
lbllbl 2012-04-18
  • 打赏
  • 举报
回复
5楼的代码,与我的不同。你的直接调用say(),异常从say()中抛出的。我的是从拦截的代码中抛出的,并不是从直接调的方法中抛出异常。
安特矮油 2012-04-18
  • 打赏
  • 举报
回复
这是我测试的结果:

public int say() throws Exception{
System.out.println("hello world!");
throw new MyException("退出错误");
}

public static void main(String[] args) throws Exception {
ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext.xml");
LogTestService service = (LogTestService)act.getBean("LogTestService");
try {
service.say();
} catch (Exception e) {
System.out.println("错误信息:" + e.getMessage());
}
}


<aop:config>
<aop:aspect ref="logManager">
<aop:pointcut id="logAOP" expression="execution(* com.study.spring.aop.service.impl.LogTestServiceImpl.say())"/>
<aop:after method="printLog" pointcut-ref="logAOP"/>
</aop:aspect>
</aop:config>

打印结果:
hello world!
spring aop test.
错误信息:退出错误
lbllbl 2012-04-17
  • 打赏
  • 举报
回复
3楼说的我当然试过,那是另外一个问题,只是我想这2个问题解决了,那个问题可能也就能解决了。2楼可能没看清问题。
minxiaohui1 2012-04-17
  • 打赏
  • 举报
回复
楼主第一个问题2楼已经给出答案了,
第二个问题,楼主在aop的before方法中抛出了异常,但是类型是Exception,何不试试抛出MyException,然后在测试方法中chatch(MyException e)试试,估计就不会报错了。
安特矮油 2012-04-17
  • 打赏
  • 举报
回复
dao.addUser("");
你这个方法有异常吗?没有,所以那句打印应该是打不出来的。
但是应该会有异常的打印
lbllbl 2012-04-17
  • 打赏
  • 举报
回复
自己顶一次

67,514

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧