静态代理
静态代理是一种设计模式,用于在不改变目标对象的情况下,增加对目标对象的控制或功能。它的基本思想是创建一个代理类,该类实现与目标类相同的接口,并在其方法中调用目标对象的方法
优点:
- 增强功能:可以在不改变目标类的情况下,增强其功能。
- 代码复用:通过代理类可以重用目标类的代码。
缺点:
- 代码膨胀:每增加一个目标类,就需要增加一个对应的代理类,导致代码量增大。
- 灵活性差:代理类在编译时就被确定,不能动态改变。
示例:
// 定义接口
interface Subject {
void request();
}
// 目标类
class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
// 代理类
class ProxySubject implements Subject {
private RealSubject realSubject;
public ProxySubject() {
this.realSubject = new RealSubject();
}
@Override
public void request() {
// 增强功能:在请求前后添加日志
System.out.println("ProxySubject: Logging before request.");
realSubject.request();
System.out.println("ProxySubject: Logging after request.");
}
}
// 测试
public class StaticProxyDemo {
public static void main(String[] args) {
// 创建代理类,ProxySubject 代理的是 Subject 类,如果不是 Subject 就不能代理,就要重新创建一个代理类
Subject proxy = new ProxySubject();
// 调用代理类的方法,内部还是会调用目标类的方法,但是代理方法增强过
proxy.request();
}
}
JDK 动态代理
静态代理最大的弊端就是每增加一种目标类就要增加一种代理类,所以静态代理除了特定的场景几乎不适用
使用 java.lang.reflect.Proxy#newProxyInstance
来创建代理类,这个方法一共三个参数:
-
目标类的类加载器
-
目标类实现的接口
-
执行处理器,是一个接口 InvocationHandler,里面只有一个方法(函数式接口)
// 创建目标对象 User user = new User(); // 代理类 User userProxy = (User) Proxy.newProxyInstance( user.getClass().getClassLoader(), // 目标类类加载器 user.getClass().getInterfaces(), // 目标类接口 new InvocationHandler() { // 执行处理器,可以使用 lambda 表达式 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 可以在方法执行前后增强、args 是参数可以动态修改 等 // 执行目标方法 Object result = method.invoke(user, args); // 返回目标方法执行结果 return result; } } ); // 使用代理类调用方法 userProxy.getName();
再一个示例
定义多个接口:
public interface SubjectA {
void requestA();
}
public interface SubjectB {
void requestB();
}
接口实现类:
public class RealSubjectA implements SubjectA {
@Override
public void requestA() {
System.out.println("RealSubjectA: Handling request A.");
}
}
public class RealSubjectB implements SubjectB {
@Override
public void requestB() {
System.out.println("RealSubjectB: Handling request B.");
}
}
执行处理器:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicInvocationHandler implements InvocationHandler {
private Object target;
public DynamicInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Proxy: Logging before request.");
Object result = method.invoke(target, args);
System.out.println("Proxy: Logging after request.");
return result;
}
}
使用:
import java.lang.reflect.Proxy;
public class DynamicProxyDemo {
public static void main(String[] args) {
// 代理 RealSubjectA
RealSubjectA realSubjectA = new RealSubjectA();
SubjectA proxyA = (SubjectA) Proxy.newProxyInstance(
realSubjectA.getClass().getClassLoader(),
realSubjectA.getClass().getInterfaces(),
new DynamicInvocationHandler(realSubjectA) // 执行处理器使用都是同一个 DynamicInvocationHandler
);
proxyA.requestA();
// 代理 RealSubjectB
RealSubjectB realSubjectB = new RealSubjectB();
SubjectB proxyB = (SubjectB) Proxy.newProxyInstance(
realSubjectB.getClass().getClassLoader(),
realSubjectB.getClass().getInterfaces(),
new DynamicInvocationHandler(realSubjectB) // // 执行处理器使用都是同一个 DynamicInvocationHandler
);
proxyB.requestB();
}
}
CGLIB 动态代理
JDK 动态代理要求目标类必须实现接口,如果目标类没有实现接口就要使用 CGLIB 动态代理,是三方实现的,所以要引入依赖
依赖:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
目标类:
public class UserService {
public void addUser(String user) {
System.out.println("Adding user: " + user);
}
}
创建 CGLIB 代理类:
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class UserServiceProxy implements MethodInterceptor {
// 创建代理对象的方法
public Object createProxy(Class<?> targetClass) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass); // 设置要代理的类
enhancer.setCallback(this); // 设置回调
return enhancer.create(); // 创建代理对象
}
@Override
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method: " + method.getName());
Object result = proxy.invokeSuper(obj, args); // 调用目标类的方法
System.out.println("After method: " + method.getName());
return result;
}
}
使用:
public class CGLIBProxyDemo {
public static void main(String[] args) {
// 创建 CGLIB 代理
UserServiceProxy proxy = new UserServiceProxy();
UserService userServiceProxy = (UserService) proxy.createProxy(UserService.class);
// 使用代理对象调用方法
userServiceProxy.addUser("John Doe");
}
}
标签:void,Object,request,代理,模式,proxy,public
From: https://www.cnblogs.com/cyrushuang/p/18471934