ThrowsAdvice是一个空接口,起标识作用
public interface ThrowsAdvice extends AfterAdvice { }
自建ThrowingAdvice类, 实现ThrowsAdvice,但是里面没有任何要重写的方法,但是里面必须写afterThrowing方法
切面类MyLogger.java
//切面类
public class MyLogger {
public void log(String msg){
System.out.println("log:"+msg);
}
}
实体类Account.java
//银行账户
public class Account {
private int id;
private String name;
private double balance;//余额
get/set方法
...
}
dao层接口AccountDao.java
public interface AccountDao {
//取款 账号减去多少钱
void withdraw(Account acc,double amt);
//存款 账号加上多少钱
void deposit(Account acc,double amt);
}
dao层实现类AccountDaoImpl.java
public class AccountDaoImpl implements AccountDao{
//取款
@Override
public void withdraw(Account acc, double amt) {
System.out.println("账号成功取款"+amt);
}
//存款
@Override
public void deposit(Account acc, double amt) {
System.out.println("账号成功存款"+amt);
}
}
service层接口IAccountService.java
public interface IAccountService {
//转账
void bankAction();
}
目标对象,service层实现类AccountServiceImpl.java,里面抛出异常
//目标对象(target)
public class AccountServiceImpl implements IAccountService{
private AccountDao accountDao;
private Account account;
get/set方法
...
@Override
public void bankAction() {
accountDao.withdraw(account, 100);
accountDao.deposit(account, 100);
throw new RuntimeException("我的异常测试");//测试异常通知
}
}
ThrowingAdvice.java
//异常通知
//负责把切面类的代码织入到目标对象中指定的方法抛出异常的时候
public class ThrowingAdvice implements ThrowsAdvice {
private MyLogger logger;
public MyLogger getLogger() {
return logger;
}
public void setLogger(MyLogger logger) {
this.logger = logger;
}
// method参数:将来调用的方法
// args参数:将来调用方法时传的参数
// target参数:目标对象
// e参数:将来调用方法所抛出的异常(要么只有这一个参数,要么这四个参数都要有)
public void afterThrowing(Method method, Object[] args, Object target, Exception e) {
logger.log("异常通知:" + e.getMessage());
}
}
throwing.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!-- 配置切面类 -->
<bean name="logger" class="com.briup.aop.aspect.MyLogger"></bean>
<!-- 配置异常通知 -->
<bean name="throwingAdvice" class="com.briup.aop.throwException.ThrowingAdvice">
<!-- 注入切面类对象 -->
<property name="logger" ref="logger"></property>
</bean>
<!-- 配置目标对象 -->
<bean name="target" class="com.briup.aop.service.AccountServiceImpl">
<!-- 注入相关的类 -->
<property name="accountDao" ref="accountDao"></property>
<property name="account" ref="account"></property>
</bean>
<!-- 配置dao层对象和account对象,为了给service注入 -->
<bean name="accountDao" class="com.briup.aop.dao.AccountDaoImpl"></bean>
<bean name="account" class="com.briup.aop.pojo.Account">
<property name="id" value="1"></property>
<property name="name" value="tom"></property>
<property name="balance" value="20000"></property>
</bean>
<!-- 配置产生对象的工厂类 -->
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 注入需要实现的接口 -->
<property name="proxyInterfaces">
<list>
<value>com.briup.aop.service.IAccountService</value>
</list>
</property>
<!-- 注入被代理的目标对象-->
<property name="target" ref="target"/>
<!-- 注入通知(拦截器) -->
<property name="interceptorNames">
<list>
<value>throwingAdvice</value>
</list>
</property>
</bean>
</beans>
测试:
@Test
public void aop_throwException() {
try {
String path = "com/briup/aop/throwException/throwing.xml";
ApplicationContext container = new ClassPathXmlApplicationContext(path);
//获取代理对象
IAccountService proxy=(IAccountService) container.getBean("proxy");
proxy.bankAction();
System.out.println("------------");
System.out.println(proxy.getClass());
} catch (Exception e) {
e.printStackTrace();
}
}