Spring AOP的实现原理以及应用场景。
AOP应用场景
- 记录日志;
- 监控方法运行时间(监控性能);
- 权限控制;
- 缓存优化(第一次调用查询数据库,将查询结果放入内存对象,第二次调用则直接从内存对象返回,不需要查询数据库);
- 事务管理(调用方法前开启事务,调用方法后提交关闭事务);
AOP实现原理
Spring中AOP的两种实现方式:
- JDK动态代理;
- Cglib动态代理;
JDK动态代理
-
引入依赖,有Spring、单元测试和日志管理;
<dependencies> <!-- Spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <!-- 单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <!-- 日志 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency> </dependencies>
-
UserDao接口
public interface UserDao { public void saveUser(); }
-
UserDao实现类
public class UserDaoImpl implements UserDao { @Override public void saveUser() { System.out.println("持久层:用户保存"); } }
-
动态代理
@Test public void test1() { final UserDao userDao = new UserDaoImpl(); // newProxyInstance的三个参数解释: // 参数1:代理类的类加载器,同目标类的类加载器 // 参数2:代理类要实现的接口列表,同目标类实现的接口列表 // 参数3:回调,是一个InvocationHandler接口的实现对象,当调用代理对象的方法时,执行的是回调中的invoke方法 //proxy为代理对象 UserDao proxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), new InvocationHandler() { @Override // 参数proxy:被代理的对象 // 参数method:执行的方法,代理对象执行哪个方法,method就是哪个方法 // 参数args:执行方法的参数 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("记录日志"); Object result = method.invoke(userDao, args); return result; } }); //代理对象执行方法 proxy.saveUser(); }
-
结果,在没有修改原有类的代码的情况下,对原有类的
Cglib动态代理
在实际开发中,可能需要对没有实现接口的类增强,用JDK动态代理的方式就没法实现。采用Cglib动态代理可以对没有实现接口的类产生代理,实际上是生成了目标类的子类来增强。
首先,需要导入Cglib所需的jar包。提示:spring已经集成了cglib,我们已经导入了spring包,所以不需要再导入其它包了。
-
创建LinkManDao类,没有实现任何接口
public class LinkManDao { public void save(){ System.out.println("持久层:联系人保存...."); } }
-
动态代理
@Test public void test2() { final LinkManDao linkManDao = new LinkManDao(); // 创建cglib核心对象 Enhancer enhancer = new Enhancer(); // 设置父类 enhancer.setSuperclass(linkManDao.getClass()); // 设置回调 enhancer.setCallback(new MethodInterceptor() { /** * 当你调用目标方法时,实质上是调用该方法 * intercept四个参数: * proxy:代理对象 * method:目标方法 * args:目标方法的形参 * methodProxy:代理方法 */ @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("记录日志"); Object result = method.invoke(linkManDao, args); return result; } }); // 创建代理对象 LinkManDao proxy = (LinkManDao) enhancer.create(); proxy.save(); }
-
结果
标题:Spring AOP的实现原理以及应用场景。
作者:zzzzchen
地址:https://www.dczzs.com/articles/2021/10/29/1635508763586.html