实现原理:
异常增强完成功能:在目标类的抛出异之前嵌入增强逻辑.
实现原理:
1. 实现接口 ThrowsAdvice,重写函数 afterThrowing ,在目标方法抛出异常之前嵌入逻辑代码,常用于事务处理的回滚
2. 利用ProxyFactoryBean代理类调用目标类方法
3.配置Spring XML
定义接口类
package com.advice;
import com.smart.domain.User;
import java.sql.SQLException;
/**
* @author Duoduo
* @version 1.0
* @date 2017/4/22 18:58
*/
public interface IUserDao {
int addUser(User user);
int updateUser(User user);
void deleteUser(User user);
void removeUser(User user) throws SQLException;
}
接口实现类
package com.advice;
import com.smart.domain.User;
import java.sql.SQLException;
/**
* @author Duoduo
* @version 1.0
* @date 2017/4/22 19:00
*/
public class UserDaoImpl implements IUserDao {
@Override
public int addUser(User user) {
System.out.println("Add user");
return 0;
}
@Override
public int updateUser(User user) {
System.out.println("Update user");
return 0;
}
@Override
public void deleteUser(User user) {
throw new RuntimeException("exception test");
}
@Override
public void removeUser(User user) throws SQLException {
throw new SQLException("SQLException Test");
}
}
定义异常增强类
package com.advice;
import org.springframework.aop.ThrowsAdvice;
import java.lang.reflect.Method;
/**
* 异常抛出增强:当抛出异常之前执行,常用于事务处理的回滚
* @author Duoduo
* @version 1.0
* @date 2017/4/23 10:34
*/
public class TransactionManagerAdvice implements ThrowsAdvice {
public void afterThrowing(Method method, Object[] args, Object target, Exception ex){
System.out.println("*******************");
System.out.println("method name : "+ method.getName());
System.out.println("after throw exception :"+ ex.getMessage() );
System.out.println("rollback ... ");
}
}
Spring XML 配置
特别注意:代理工厂是 ProxyFactoryBean 不是 ProxyFactory
<!-- 代理设置 -->
<bean id="userDaoImpl" class="com.advice.UserDaoImpl"/>
<bean id="transactionManagerAdvice" class="com.advice.TransactionManagerAdvice"/>
<bean id="addUserProxyFactory" class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.advice.IUserDao"
p:target-ref="userDaoImpl"
p:interceptorNames="transactionManagerAdvice"/>
两种调用方式:
1.根据XML配置来进行调用测试
2.自己创建代理来进行测试
另种方法都需要注意:此处代理获取的是代理Bean,指向的是Interface的代理。
@Test
public void deleteUserTest(){
System.out.println("************ deleteUserTest ************");
IUserDao userDao = new UserDaoImpl();
ThrowsAdvice throwsAdvice = new TransactionManagerAdvice();
//创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
//设置代理目标类
proxyFactory.setTarget(userDao);
//为代理添加增强
proxyFactory.addAdvice(throwsAdvice);
//生成代理实例
IUserDao proxyUserDao = (IUserDao)proxyFactory.getProxy();
try {
proxyUserDao.removeUser(user);
} catch (SQLException e) {
e.printStackTrace();
}
proxyUserDao.deleteUser(user);
}
测试结果
************ deleteUserTest *******************************
method name : removeUser
after throw exception :SQLException Test
rollback ...
java.sql.SQLException: SQLException Test
at com.advice.UserDaoImpl.removeUser(UserDaoImpl.java:32)
at com.advice.UserDaoImpl$$FastClassBySpringCGLIB$$5dedbffe.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:125)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656)
at com.advice.UserDaoImpl$$EnhancerBySpringCGLIB$$348998ab.removeUser(<generated>)
at com.advice.UserDaoAdviceTest.deleteUserTest(UserDaoAdviceTest.java:123)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
*******************
method name : deleteUser
after throw exception :exception test
rollback ...
四月 23, 2017 4:16:31 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@670002: startup date [Sun Apr 23 16:16:31 CST 2017]; root of context hierarchy
四月 23, 2017 4:16:31 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [spring-another-context.xml]
java.lang.RuntimeException: exception test
at com.advice.UserDaoImpl.deleteUser(UserDaoImpl.java:27)
at com.advice.UserDaoImpl$$FastClassBySpringCGLIB$$5dedbffe.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:125)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656)
at com.advice.UserDaoImpl$$EnhancerBySpringCGLIB$$348998ab.deleteUser(<generated>)
at com.advice.UserDaoAdviceTest.deleteUserTest(UserDaoAdviceTest.java:128)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)