自己写的AroundAdvice实现org.aopalliance.intercept.MethodInterceptor.MethodInterceptor,重写里面的方法invoke()
与前置通知相比,大概的类不变,只需要改变AroundAdvice以及xml
环绕通知
特点:需要通过invocation.proceed()来调用目标对象的指定的方法
切面类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);
}
}
环绕通知,实现MethodInterceptor,重写方法invoke,invocation.proceed()表示真正调用方法
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
//环绕通知
//负责把切面类的代码织入到目标对象中指定的方法执行之前和执行之后
public class AroundAdvice implements MethodInterceptor {
private MyLogger logger;
public MyLogger getLogger() {
return logger;
}
public void setLogger(MyLogger logger) {
this.logger = logger;
}
// invocation参数:使用该参数可以调用到目标对象中指定的方法
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
String name = invocation.getMethod().getName();
logger.log("环绕通知-" + name + "方法开始");//之前
// 调用目标对象的指定方法
Object result = invocation.proceed();//真正调用目标方法
logger.log("环绕通知-" + name + "方法结束");//之后
return result;
}
}
around.xml
需要改变name=“aroundAdvice”,<value>aroundAdvice</value>
<?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="aroundAdvice" class="com.briup.aop.around.AroundAdvice">
<!-- 注入切面类对象 -->
<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>aroundAdvice</value>
</list>
</property>
</bean>
</beans>
测试:
@Test
public void aop_around() {
try {
String path = "com/briup/aop/around/around.xml";
ApplicationContext container = new ClassPathXmlApplicationContext(path);
//获取代理对象
IAccountService proxy=(IAccountService) container.getBean("proxy");
proxy.bankAction();
proxy.toString(); //toString也被代理了
} catch (Exception e) {
e.printStackTrace();
}
}