在介绍AOP之前,先给大家介绍一下动态代理的知识
先来给大家举个简单的例子,现在有如下用户接口和其实现类(为方便起见,实现类中只打印对应语句)
package com.zy.service;
public interface userService
{
public void selectUser();
public void insertUser();
}
package com.zy.service;
public class userServiceImpl implements userService
{
@Override
public void selectUser()
{
System.out.println("查找用户");
}
@Override
public void insertUser()
{
System.out.println("插入用户");
}
}
现在要给这两个方法添加两个功能: 在执行前 添加记录时间功能 在执行后添加 **记录日志**功能,我们要如何实现呢?
方式1:大多数人可能会想,直接在两个方法中都添加 这两个新功能 即可,如下所示
public class userServiceImpl implements userService
{
@Override
public void selectUser()
{
System.out.println("执行时间为:" + new Date());
System.out.println("查找用户");
System.out.println("打印日志信息");
}
@Override
public void insertUser()
{
System.out.println("执行时间为:" + new Date());
System.out.println("插入用户");
System.out.println("打印日志信息");
}
}
但是这样就改变了原有代码,并且原本处理业务的代码与新添加的无关业务代码就融合在了一起,并且大量重复,这就导致了方法很杂乱,而且如果我们修改无关业务的代码就要在每个函数中都进行修改,那我们应该怎么优化呢?
方式2:我们将无关业务的代码单独提取出来,封装到一个工具类,并在业务代码中调用即可,如下所示
public class otherService
{
public static void getTime()
{
System.out.println("执行时间为:" + new Date());
}
public static void getLog()
{
System.out.println("打印日志信息");
}
}
@Override
public void selectUser()
{
otherService.getTime();
System.out.println("查找用户");
otherService.getLog();
}
@Override
public void insertUser()
{
otherService.getTime();
System.out.println("插入用户");
otherService.getLog();
}
这样解决了部分问题,但是我们还可以发现,业务类代码中还是调用者非业务代码,耦合性还是太高,这就引出了我们的动态代理~
动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类。代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架。
基本过程如下所示,由代理类通过业务接口创建代理类对象,最后返回代理类对象。
方式3:我们接着用JDK自带的动态代理的方式,解决上述需求
首先我们创建UserService代理类 实现InvocationHandler接口
package com.zy.service;
public class UserProxy implements InvocationHandler
{
private Object target;//代理接口(目标对象)
public UserProxy(Object target)
{
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
otherService.getTime();//打印时间
Object invoke = method.invoke(target, args);
otherService.getLog();//打印日志
return invoke;
}
public void setTarget(Object target)
{
this.target = target;
}
}
接着为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类
public void test()
{
//首先创建目标对象
UserServiceImpl target = new UserServiceImpl();
//创建InvocationHandler对象
UserProxy proxy = new UserProxy(target);
//使用Proxy创建代理
UserService userService = (UserService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), proxy);
//测试代理类对象
userService.insertUser();
}
结果如下
这样的话,我们没有修改原有的业务代码却达成了添加新功能的作用。
动态代理作用通过上面的例子,我们可以发现动态代理有以下作用
- 可以在目标类源代码不改变的情况下,增加功能。
- 可以减少代码的重复。
- 可以使程序员专注业务逻辑代码。
- 可以使代码解耦合,让的业务功能与非业务功能分离。



