先配置spring相关的jar包,需要额外添加aop的库:
定义一个持久层接口:userDao
package com.aop;
public interface UserDao {
public void addUser(String id, String name);
}
实现该接口的功能:
package com.aop;
public class UserDaoImpl implements UserDao {
@Override
public void addUser(String id, String name) {
System.out.println("==============addUser方法正在逻辑执行============");
}
}
我们需要定义一个 切面类,在该类中去实现为userDao中添加新的功能。比如日志提醒功能。
如下:环绕通知需要 实现 MethodInterceptor 接口
package com.aop;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class LogAspect implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
//MethodInvocation 该方法通过监测切面进行拦截方法
//执行正式逻辑之前输出的内容
System.out.print(arg0.getMethod());
System.out.println("------表示日志开始:环绕通知开始------------");
//执行逻辑 这个逻辑就是执行userDao中的addUser()方法。
Object obj = arg0.proceed();
//执行逻辑后输出的内容
System.out.println("--------代理日志结束:环绕通知结束------------");
return obj;
}
}
解释:1. MethodInvocation 该方法通过监测切面进行拦截方法,会检测到userDao中的addUser()方法中有切面,会自动拦截下这个方法,并且在方法执行的前后会添加日志
2. arg0.proceed(); 执行逻辑 这个逻辑就是执行userDao中的addUser()方法。 就是你执行你的addUser()方法,切面只负责添加日志
通过xml配置文件将 userDao和切面类(代理类)链接起来。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
<!-- target object -->
<bean id="userDao" class="com.aop.UserDaoImpl"/>
<!-- 切面 -->
<bean id="logAspect" class="com.aop.LogAspect"/>
<!-- aop的代理: ProxyFactoryBean -->
<bean id="userDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 需要代理哪些接口? -->
<property name="proxyInterfaces" value="com.aop.UserDao"/>
<!-- 目标对象? ref 表示引用类型 -->
<property name="target" ref="userDao"/>
<!-- 拦截器的名字: 也就是切面类的名字 ? -->
<property name="interceptorNames" value="logAspect"/>
<!-- 代理类是不是接口,false表示JDK代理 -->
<property name="proxyTargetClass" value="false"/>
</bean>
</beans>
注释有详细的解释,两个类相互联系
我们来测试一下:
package com.aop;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
class TestUserDao {
@Test
void testAddUser() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//
UserDao userDao = context.getBean("userDaoProxy", UserDao.class);
userDao.addUser("zhm", "zqw");
}
}
展示结果:
aop说明白就是代理userDao去做些自己不想做的事情,这样userDao就能够专注于自己的业务实现,不用去理会杂七杂八的功能。把日志功能交给代理即可。
我们通过对比输出,不难发现,test测试程序执行的就是代理类。
我们来还原下:如果不配置aop,我们应该怎么做呢! 我们应该用代理类去实现UserDao
package com.aop;
public class UserDaoProxy implements UserDao {
@Override
public void addUser(String id, String name) {
System.out.println("------表示日志开始:环绕通知开始------------");
//执行逻辑 这个逻辑就是执行userDao中的addUser()方法。
UserDao userDao = new UserDao();
userDao.addUser("zhm", "zqw");
//执行逻辑后输出的内容
System.out.println("--------代理日志结束:环绕通知结束------------");
}
}
然后调用代理类UserDaoProxy中的addUser()方法即可,原理是一样的。