静态代理
eg: 我们在商店买商品,而商店的商品又来源于厂商,此时商店的作用便是代理
1. 定义服务接口
java
public interface UserService {
void select();
void update();
}
2. 实现服务接口的类
java
public class UserServiceImpl implements UserService {
@Override
public void select() {
System.out.println("这是查找");
}
@Override
public void update() {
System.out.println("这是修改");
}
}
3. 创建代理类
代理类同样实现 UserService
接口,并在其中添加扩展逻辑。
java
public class UserServiceProxy implements UserService {
private UserServiceImpl userService = new UserServiceImpl();
@Override
public void select() {
long begin = System.currentTimeMillis();
userService.select();
long end = System.currentTimeMillis();
System.out.println("select执行时间为" + (end - begin) + "毫秒");
}
@Override
public void update() {
long begin = System.currentTimeMillis();
userService.update();
long end = System.currentTimeMillis();
System.out.println("update执行时间为" + (end - begin) + "毫秒");
}
}
静态代理的问题
虽然静态代理允许我们在不修改原有业务逻辑代码的情况下添加额外逻辑,但它也存在以下缺点:
- 代理类数量繁多:当有多个目标类时,需要为每个目标类创建对应的代理类,导致代理类数量激增。
- 耦合度高:如果在接口中增加或修改功能,需要同时修改实现类和代理类,降低了代码的灵活性。
动态代理
动态代理利用 JDK 的反射机制,能够在运行时创建代理对象,避免了静态代理的缺点。
动态代理的实现方式
- 基于jdk的动态代理:使用java反射技术实现(主要有invocatoionHandler接口,Method和Proxy类)
- 基于cglib动态代理:cglib为第三方的工具库,主要用来创建代理对象。目标类只需要继承cglib生成一个被代理对象的子类作为代理(核心为:MethodIntercepter接口和Enhancer类)
注意:基于jdk动态代理必须要实现接口,若是没有实现接口则使用cglib来创建动态代理
其中:
- Method类:
- method表示代理所调用的目标方法
- Proxy类
- 通过该类可以生成代理对象,代理对象的创建是由jdk提供的,我们只是负责调Proxy类中的方法来拿到这个代理对象
- 调用Proxy类中的静态方法newProxyInstance()来创建一个代理对象
java
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
- newProxyInstance参数说明:
- loader表示目标对象的类加载器,固定写法:目标对象.getClass().getClassLoader();
- interfaces表示目标对象所实现的接口,接口多继承,因此是个数组。固定写法:目标对象.getClass().getInterface();
- h表示代理类所要完成的功能
返回值就是代理类对象,并且在该对象创建时已经说明了,该代理类对象所代理的目标对象是谁,该目标对象完成了那些功能,该代理类所要完成的功能
JDK 动态代理的步骤
- 定义被代理的接口
java
public interface OrderService {
void create();
}
- 实现被代理接口的类
java
public class OrderServiceImpl implements OrderService {
@Override
public void create() {
System.out.println("执行创建订单");
}
}
- 创建代理类并实现
InvocationHandler
接口
java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class PerformanceInvocationHandler implements InvocationHandler {
private Object real;
public PerformanceInvocationHandler(Object real) {
this.real = real;
}
/**
* @param proxy 代理对象
* @param method 当前执行的方法对象
* @param args 参数列表
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long begin = System.currentTimeMillis();
Object result = method.invoke(real, args);
long end = System.currentTimeMillis();
System.out.println("执行方法耗时" + (end - begin) + "毫秒");
return result;
}
}
- 测试动态代理
java
import java.lang.reflect.Proxy;
public class Test01 {
public static void main(String[] args) {
// 创建被代理对象
OrderServiceImpl orderService = new OrderServiceImpl();
// 获取类加载器
ClassLoader classLoader = orderService.getClass().getClassLoader();
// 获取接口
Class<?>[] interfaces = orderService.getClass().getInterfaces();
// 创建 InvocationHandler
PerformanceInvocationHandler handler = new PerformanceInvocationHandler(orderService);
// 创建动态代理对象
OrderService orderServiceProxy = (OrderService) Proxy.newProxyInstance(classLoader, interfaces, handler);
// 调用代理的方法
orderServiceProxy.create();
}
}
输出结果
执行创建订单
执行方法耗时1毫秒
总结
通过使用静态代理和动态代理模式,我们能够有效地扩展对象的功能而无需修改原有业务逻辑。尽管静态代理适用于简单场景,但随着系统的复杂性增加,动态代理提供了更高的灵活性和可扩展性,尤其是在处理多个目标对象时。